PHP反序列化绕过限制Tricks
/PHP序列化的时候private和protected变量会引入不可见字符\x00
,输出和复制的时候可能会遗失这些信息,导致反序列化的时候出错。
private属性序列化的时候会引入两个\x00
,注意这两个\x00
就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,如图,url编码后就可以看得很清楚了:
同理,protected属性会引入\x00*\x00
。
此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。比如s:5:"A<null_byte>B<cr><lf>";̀ -> S:5:"A\00B\09\0D";
phpggc这个工具就支持这个选项:https://github.com/ambionics/phpggc#ascii-strings
此时生成的Payload更加可读,也方便传输。
今年网鼎杯出了一道PHP反序列化的题,需要绕过限制,限制是不允许传入一些控制字符等:
其中一种思路就是使用这种技巧,在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。在测试绕过一些WAF的时候可以用到了这个方法。
其他的解法可参考:
- pravite和Protected成员的序列化
- 7.2及以上版本的PHP,public属性可以覆盖替代private