PHP反序列化总结

漏洞成因

Demo:

<?php
class A{
public $target = "demo";
function __destruct(){
        echo "destructing!<br/>";
        echo $this->target."<br/>";
        echo "destructed!<br/>";
}
}
$a = $_GET['test'];
$a_unser = unserialize($a);
?>

在这里我们可以构造一个对象,控制$test的值,以实现控制数据流的目的

生成序列化字符串:

<?php
class A{
public $target = "w2t3rp2dd13r";
}

$a = serialize(new A);
echo $a;
?>

常见绕过方式

_wakeup绕过:

__wakeup()是用在反序列化操作中。unserialize()会检查存在一个__wakeup()方法。如果存在,则先会调用__wakeup()方法。

<?php
class A{
function __wakeup(){
echo 'Hello';
} 
}
$c = new A();
$d=unserialize('O:1:"A":0:{}');
?>

存在wakeup函数,所以会输入hello

<?php 
class Student{ 
public $full_name = 'zhangsan';
public $score = 150;
public $grades = array();

function __wakeup() {
echo "__wakeup is invoked";
}
}

$s = new Student();
var_dump(serialize($s));
?>

这里会输出student的实例序列化字符串

O:7:"Student":3:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}

student后的3代表该类存在3个属性

而当该属性大于真实值时代码就会跳过_wakeup()函数执行

所以当输入序列化字符串为:
O:7:”Student”:4:{s:9:”full_name”;s:8:”zhangsan”;s:5:”score”;i:150;s:6:”grades”;a:0:{}}

时,就不会执行_wakeup()函数。