反序列化漏洞
本文参考
一文从PHP反序列化入门到进阶
原理
序列化的原理就是用过函数将一个类型变成一串文本保存起来,而反序列化又是将一串序列化过的文本还原成一个对象。通过修改序列化字符串的方法来执行想要的操作。
Class 类 => 函数和变量的集合
函数
serialize() # 序列化对象
unserialize() # 反序列化字符串成对象
序列化后的内容要和类捆绑
篡改参数的方法
<?php
show_source(__FILE__);
class he{
var $h = "Hello";
}
serialize(new he);
#O:2:"he":1:{s:1:"h";s:5:"Hello";}
$s = 'O:2:"he":1:{s:1:"h";s:5:"Hell1";}';
var_dump(unserialize($s));
?>
在篡改对象内的变量的时候需要注意类和内容长度。
调用危险函数
show_source(__FILE__);
class se{
public function ld(){
eval($this->source);
}
}
$s = unserialize("O:2:"se":0:{}");
如上图所示,我们需要先篡改上面的source变量来,随后我们需要执行ld函数来对source变量的内容进行解析。
<?php
show_source(__FILE__);
class se{
public function ld(){
eval($this->source);
}
}
#$s = unserialize('O:2:"se":0:{}');
$s = new se;
$s->source = "phpinfo();"; # 修改这里后进行序列化,随后传参进上面程序
var_dump(serialize($s)); # 得到结果
# O:2:"se":1:{s:6:"source";s:10:"phpinfo();";}
?>
当我们修改完对象以后发现该程序并未像我们所想一样执行phpinfo(),但也并未失败,只是函数未被调用,我们需要调用函数。
魔术方法
魔术方法,其实就是一个满足条件自动触发的方法
常见的魔术方法
- __construct 对象创建时自动调用
- __destruct 对象销毁时自动调用
- __wakeup 在使用unserialize方法时自动调用
当目标对象被private、protected修饰时反序列化漏洞的利用
private属性序列化的时候格式是%00类名%00成员名
protect属性序列化的时候格式是%00*%00成员名
<?php
class test{
public $name="ghtwf01";
private $age="18";
protected $sex="man";
}
$a=new test();
$a=serialize($a);
print_r($a);
?>
# 返回值
__wakeup绕过
__wakeup魔法函数简介
unserialize()
会检查是否存在一个 __wakeup()
方法。如果存在,则会先调用 __wakeup()
方法,预先准备对象需要的资源
反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup()
的执行