php反序列化一道题详解
https://www.cnblogs.com/bkofyZ/p/17660907.html#comment_form_container
[NISACTF 2022]popchains
什么是序列化
定义:序列化就是将一个对象转换成字符串,反序列化则是将字符串重新恢复成对象
PHP序列化函数:serialize()
PHP反序列化函数:unserialize()
几个常用的魔术方法:
名称 | 触发时机 |
---|---|
__construct() | 在对象实例化(创建对象)的时候自动触发 |
__destruct() | 在销毁对象的时候自动触发 |
__wakeup() | 执行unserialize()时,先会调用这个函数 |
__sleep() | 执行serialize()时,先会调用这个函数 |
__call() | 在对象上下文中调用不可访问的方法时触发 |
__get() | 访问私有或不存在的成员属性的时候自动触发 |
__set() | 对私有成员属性进行设置值时自动触发 |
__isset() | 对私有成员属性进行 isset 进行检查时自动触发 |
__unset() | 对私有成员属性进行 unset 进行检查时自动触发 |
__toString() | 把类当作字符串使用时触发 |
__invoke() | 当尝试将对象调用为函数时触发 |
一般做题顺序
构造pop链,找出它的起点或者终点,再利用魔术方法的触发条件和题目的代码结构,将POP链完善
POP链:就是利用魔法方法进行多次跳转后获取敏感数据的一种payload
接下来开始代码审计
1 |
|
(1)找到终点,Try_work_Hard的append()
想到可以利用php伪协议读取数据流,那么怎么触发append()呢,发现下面的__invoke()
可以触发append();
(2)接着Try_work_Hard::__invoke()
__invoke
: 当尝试将对象调用为函数时触发,看了一圈,发现$Make_a_Change类里面的$effort是可控的,且__get
方法可以返回可控的函数,那就想办法让$effort为Try_work_Hard
的类的对象
(3)接着Make_a_Change()::__get()
__get
访问私有或不存在的成员属性的时候自动触发,利用它
1 | public function __toString(){ |
(4)接着Road_is_Long::__toString()
实例化化之后,让它的string指向Make_a_Change的类的对象,
(5)继续Road_is_Long::__wakeup()
__toString: 把类当作字符串使用时触发,
因为有protected属性的$var,这反序列化后会带特殊符号%00(url编码),这个你复制粘贴不过来,但是urlencode可以显示出来好复制,不用你之后改
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Echo!