PHP序列化反序列化以及其中的漏洞(一)

__wakeup()函数用法

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

1
2
3
4
5
6
7
8
9
<?php
class A{
function __wakeup(){
echo 'Hello';
}
}
$c = new A();
$d=unserialize('O:1:"A":0:{}');
?>

最后页面输出了Hello。在反序列化的时候存在__wakeup()函数,所以最后就会输出Hello__wakeup()函数漏洞说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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:{}}。其中在Stuedent类后面有一个数字3,整个3表示的就是Student类存在3个属性。
__wakeup()漏洞就是与整个属性个数值有关。当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。
当我们将上述的序列化的字符串中的对象属性修改为5,变为
O:7:"Student":5:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}
最后执行运行的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Student{  
public $full_name = 'zhangsan';
public $score = 150;
public $grades = array();

function __wakeup() {
echo "__wakeup is invoked";
}
function __destruct() {
var_dump($this);
}
}

$s = new Student();
$stu = unserialize('O:7:"Student":5:{s:9:"full_name";s:8:"zhangsan";s:5:"score";i:150;s:6:"grades";a:0:{}}');

可以看到这样就成功地绕过了__wakeup()函数。

参考:https://blog.spoock.com/2016/11/03/php-wakeup/
(还没完结,记得补)

PHP序列化反序列化以及其中的漏洞(一)

http://example.com/2021/02/22/wakeup-函数漏洞以及实际漏洞分析/

Author

vague huang

Posted on

2021-02-22

Updated on

2021-02-22

Licensed under

Comments