serialize:函数用于序列化对象或数组,并返回一个字符串
unserialize:函数用于将通过serialize函数序列化后的对象或数组进行反序列化,并返回原始的对象结构
PHP反序列化漏洞利用前提
(1) unserialize函数的参数可控
(2) 脚本中存在一个构造函数construct()、析构函数destruct()、__wakeup函数中有向php文件中写数据的操作的类
(3) 所写的内容需要有对象中的成员变量的值
private属性序列化的时候格式是 %00类名%00成员名 如testname (test->类名name->成员名)
protected属性序列化的时候格式是 %00%00成员名 如name (name->成员名)
PHP中var关键字在类内部等同于public**序列化只序列化属性,不序列化方法**,因此
反序列化的时候要保证在当前的作用域环境下有该类存在,类属
PHP反序列化漏洞
PHP类中有一种特殊函数存在并称他们为魔法函数(magic函数),命令都是以符号__开头,例如如下:
__construct() 当一个对象创建时触发
__destruct() 当一个对象被销毁时触发
__toString() 把类当作字符串使用时触发
__call() 在对象上下文中调用不可访问的方法时触发
__callStatic() 在静态上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据时
__set() 用于将数据写入不可访问的属性
__wakeup() 使用unserialize之后触发
__sleep() 使用serialize之前触发
__isset() 在不可访问的属性上调用isset()或empty()触发
__unset() 在不可访问的属性上使用unset()时触发
__invoke() 当脚本尝试将对象调用为函数时触发
__autoload() 尝试加载未定义的类时触发
__clone() 当对象复制完成时触发
PHP通过string serialize ( mixed $value )和mixed unserialize ( string $str )两个函数实现序列化和反序列化。
下面是比较典型的PHP反序列化漏洞中可能会用到的魔术方法:
void wakeup ( void )
unserialize( )会检查是否存在一个_wakeup( ) 方法。如果存在,则会先调用_wakeup 方法,预先准备对象需要的资源。
void construct ([ mixed $args [, $… ]])
具有构造函数的类会在每次创建新对象时先调用此方法。(怎么理解先调用,在有wakeup,toString,这个函数是具有构造函数的类时先调用,如 :public function __construct($file)
{
$this->file = $file;
}
void destruct ( void )
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。(不太懂)
public string toString ( void )
toString( ) 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj;应该显示些什么。
此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。
性就是唯一的攻击突破口
(上文提到的toString()触发条件非常多)
wakeup()
绕过wakeup,A属性大于真实属性,比如原来是1,就写2就行;
利用CVE-2016-7124漏洞,当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过wakeup的执行
一些文章:
https://blog.csdn.net/qq_43380549/article/details/101265818
https://xz.aliyun.com/t/3674