PHP 反序列化漏洞学习及CVE-2016-7124漏洞复现

2019-05-25  本文已影响0人  鸡翅儿

序列化与反序列化了解

<?php 
class test{
  public $name = "wcute";
  public $age = "18";
}

$fairy = new test();
echo serialize($fairy);
 ?>
图片.png

test.php

<?php 
class test{
  public $name = "wcute";
  public $age = "18";
}

$fairy = new test();
$s_fairy = serialize($fairy);
$uns_fairy = unserialize($s_fairy);
var_dump($uns_fairy);      # 打印对象
 ?>
图片.png

魔术方法

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。
__construct()__destruct()__call()__callStatic()__get()__set()__isset()__unset()__sleep()__wakeup()__toString()__invoke()__set_state()__clone()__debugInfo() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。

常用魔术方法举例:

反序列化漏洞

PHP 中的魔术方法通常会因为某些条件触发执行,所以在unserialize ()的参数可控时,通过一定条件构造恶意序列化代码触发魔术方法,可造成严重代码执行等危害。

实例一

URL:http://120.79.33.253:9001/


图片.png

对传入的 str 参数值反序列化后与 KEY 的值相等即输出flag
因此只需将 KEY 的值序列化一下然后传给 str 参数即可
如图编写代码获取序列化值


图片.png
传值获取 flag
图片.png
实例二:__wakeup()魔术方法绕过(CVE-2016-7124)
<?php 

class test{
    public $name = "fairy";
    public function __wakeup(){
        echo "this is __wakeup<br>";
    }
    public function __destruct(){
        echo "this is __destruct<br>";
    }
}

// $s = new test();
// echo serialize($s);  
// $s = O:4:"test":1:{s:4:"name";s:5:"fairy";}

$str = $_GET["s"];
@$un_str = unserialize($str);

echo $un_str->name."<br>";

 ?>

脚本上标明接收s参数,对其反序列化后输出name属性的值
为了方便观察,我将传入的s参数的name属性值更改为xss代码
访问test.php
页面显示语句代表反序列化之前先调用了__wakeup 方法,

图片.png
点击确定后,页面完成后自动执行__destruct方法
图片.png
将传入的序列化数据的对象变量个数由1更改为2,页面只执行了__destruct方法,而且输出name属性时报错,是由于反序列化数据时失败无法创建对象。
图片.png
<?php 
class test{
    public $name = "fairy";

    public function __wakeup(){
        echo "this is __wakeup<br>";
        foreach(get_object_vars($this) as $k => $v) {
                $this->$k = null;
        }
    }
    public function __destruct(){
        echo "this is __destruct<br>";
        $fp = fopen("D:\\phpStudy\\WWW\\wcute.php","w");
        fputs($fp,$this->name);
        fclose($fp);
    }
}

// $s = new test();
// echo serialize($s);  
// $s = O:4:"test":1:{s:4:"name";s:5:"fairy";}

$str = $_GET["s"];
@$un_str = unserialize($str);

echo $un_str->name."<br>";
 ?>

其中 __destruct方法在调用时将name参数写入wcute.php文件
但是由于__wakeup方法清除了对象属性,所以在调用__destruct时已经没有了name属性,因此文件将会写入失败,XSS代码也不会执行。


图片.png

将对象属性个数改为2继续尝试,成功绕过__wakeup方法执行,将代码写入文件


图片.png

参考链接:
https://secure.php.net/manual/zh/language.oop5.magic.php
https://blog.csdn.net/dyw_666666/article/details/90199606
https://xz.aliyun.com/t/378#toc-4

上一篇 下一篇

猜你喜欢

热点阅读