Noting of [安洵杯 2019]easy_serialize_php
又是一题字符逃逸, 不过还有其他要注意的点
概述
这题考察的点有:
- 反序列化字符逃逸
extract()
变量覆盖
代码审计
提示说phpinfo()
中有东西, 找了一下发现有auto_append_file: d0g3_f1ag.php
auto_append_file
: 设置每个php中都自动require一个文件
中间有个extract($_POST)
, 可能存在变量覆盖
在代码的最后, 存在file_get_contents(base64_decode($userinfo['img']))
看参数是否可控, 可以看到有两行$userinfo = unserialize($serialize_info)
$serialize_info = filter(serialize($_SESSION))
确认有序列化和反序列化, 而$serialize_info
在序列化之后存在一个过滤使得字符减少 可能存在字符逃逸
来细细看一下$_SESSION
1 | $_SESSION = array( |
可以看到有两个参数是可以控制的, 但"img"
会进行一次sha1
加密, 反序列化后却不进行sha1
解密, 所以无论输入什么基本都是无效的…
而"function"
是可控, 且存在字符逃逸, 但如果要执行file_get_contents()
, 必须有$function='show_image'
, 在$function
的值赋给$_SESSION
之后, 存在一个$extract($_POST)
, 我们可以利用这个修改$function
为show_image
到这里思路就清楚了:
file_get_contents(base64_decode($userinfo['img']))
参数可控 -> 利用字符逃逸从"funtion"
控制"img"
-> 利用 extract()
变量覆盖修改$function
为show_image
反序列化字符逃逸
总结了挺多次了…
这次的filter
是字符减少的替换, 需要利用数组来进行逃逸, 具体原理不多讲了, 可以看反序列化那篇笔记
extract()
变量覆盖
这个还是第一次遇到,.
extract()
函数从数组中将变量导入到当前的符号表。
也就是说参数是个数组, 并且根据键对值来创造变量, 而且可以覆盖前面的变量, 这样就可以造成变量覆盖了
payload 构造
字符逃逸的构造也总结很多次了, 这次就简单的说一下
这题主要就是构造字符逃逸的payload, 我们需要最后"img" => base64encode("d0g3_f1ag.php")
老套路, 先构造一个
1 | $_SESSION["user"] = 'guest'; |
再慢慢尝试通过字符减少把一个双引号闭合, 最后可以构造出payload:
1 | ?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc= |
EXP
GET
方式传?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc=
POST
方式传function=show_image
不过结果发现flag并不在d0g3_f1ag.php
中,d0g3_f1ag.php
中只有一句 $flag = 'flag in /d0g3_fllllllag';
那就再构造一次
?f[]=phpphpphpphp&f[]=";i:1;s:1:"1";}s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn
别忘了POST
, 然后就能看到flag了
后记
做完题后翻了下别的师傅的wp, 发现别的师傅都是GET
传f=show_image
, POST
直接对$_SESSION['user']
和$_SESSION['function']
做文章, 这样就不需要通过数组来进行字符逃逸了, 这也是一种思路, 而且可以控制的变量更多了(我脑子怎么就没转过来…
不过因为脑子没转过来也解锁了控制一个变量的时候, 利用数字来进行字符减少的字符逃逸!