php 反序列化字符逃逸 1 例
当程序在反序列化之前,对反序列化字符串进行了过滤替换,导致键值长度发生变化,但是,键值记录长度未正确修改,在序列化时,错误的引用了键值长度,导致变量被覆盖。
代码
1 |
|
BUUCTF在线评测 (buuoj.cn) 安洵杯 2019 easy_serialize_php 1
解的时候,由于直接操作 http 报文,忽略了参数,导致结果一直不对….
解析
看第 35 行注释内容,我们看一下 , 在 phpinfo 中发现一行内容
image-20220804194745150
得到了 flag 的位置
代码在 30 行将 _session 序列化,然后再 37 行进行了反序列化给变量 userinfo , 并且输出 userinfo['img'] , 我们只要能够控制 img 的值,就能任意文件读取。控制 img 的值成了关键一步。
第 24 行读取 get 参数,并赋值给 _session , 但是,对于用户输入进行了 sha1 散列运算,导致并无法实际控制最终的 img 的值。
注意到 30 行,进行序列化时,对序列化的结果进行了过滤,查看 filter 实现,只是将关键字删除。这个操作会导致反序列化时,字段记录长度和实际长度不符,导致字符串逃逸。
我们实际控制的输入参数只有 function 和 img ,img 由于 sha1 运算等于不可控。但是,在 18 行有 extract 函数,该函数的作用是 将变量从数组中导入到当前的符号表中。 默认会覆盖变量当前值。
所以,我们可以在 POST 数据中构造数据控制当前的变量值。 根据 extract 所在代码行数来看,此时唯一不可精准控制的变量就是 img 了。不过,对于反序列化字符逃逸,足够了。
构造以下 POST 数据
1 | _SESSION[user]=guestflagflagflagflagphpphp& |
该数据有三个参数 _SESSION[user] 、 function和 _SESSION[function],当然,对于 function 参数,也可以直接通过 url 传递。
在 18 行 extract 之后,_SESSION 的值将被覆盖为:
1 | array( |
function 的值被覆盖为 show_image
将 _SESSION 反序列化之后为
1 | a:3:{s:4:"user";s:27:"guestflagflagflagflagphpphp";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";} |
经过 filter 过滤之后结果为
1 | a:3:{s:4:"user";s:27:"guest";s:8:"function";s:73:";s:8:"function";s:10:"show_image";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";} |
此时,在反序列化时,user 字段记录长度为 27 , 但实际长度只有 5 了,所以,将往后读多取 22 字符导致错误反序列化。我们构造的 function 字段值成为了整条序列化记录的后半段,而原始的后半段数据将被舍弃。img 的值被反序列化为我们设置的 ZDBnM19mMWFnLnBocA==
payload
POST 数据
1 | _SESSION[user]=guestflagflagflagflagphpphp& |
image-20220804202609934
Author: 哒琳
Permalink: http://blog.jieis.cn/2022/97e8fad6-d531-4a85-9b42-0373014f4713.html
Comments