当前位置 : 主页 > 网络编程 > PHP >

详解PHP反序列化漏洞示例与原理

来源:互联网 收集:自由互联 发布时间:2023-01-31
目录 预备知识 PHP序列化与反序列化 序列化字符串格式 PHP魔术方法 示例 反序列化漏洞 构造函数析构函数 CVE-2016-7124 预备知识 PHP序列化与反序列化 序列化:将一个复杂的数据类型(如
目录
  • 预备知识
    • PHP序列化与反序列化
    • 序列化字符串格式
    • PHP魔术方法
    • 示例
  • 反序列化漏洞
    • 构造函数&析构函数
    • CVE-2016-7124

预备知识

PHP序列化与反序列化

序列化:将一个复杂的数据类型(如对象、数组、变量等)转换为字符串表示,以便于在网络中传输和在数据库中存储。在PHP语言中使用serialize()函数实现。

反序列化:将一个序列化的字符串重新转换为一个具体的数据类型。在PHP语言中使用unserialize()函数实现。 PHP对象中只有数据会被序列化,方法不会被序列化。

序列化字符串格式

PHP中经过序列化的字符串格式如下:

类型:类名长度:“类名”:类属性数量:{属性类型:属性长度:“属性内容”}

序列化字符串中的属性命名规则:如果变量为public,则值保持不变;如果变量为private,则在值开头加上类名前缀;如果变量为protected,则在值开头加*符号。

下面给出序列化字符串中的属性类型:

类型解释s:length:“value”字符串i:value整数值d:value浮点数值b:value布尔值a:length:{…}数组O:length:“name”:number:{…}对象NNULL

PHP魔术方法

简介:魔术方法是一种以2个下划线开头的特殊方法,对一个对象执行魔术方法时会覆盖PHP默认的操作。

常见的PHP魔术方法如下:

方法调用时间__construct(构造函数)创建新对象时__destruct (析构函数)销毁对象时__call在对象中调用不可用方法时__callStatic在上下文中调用不可用方法时__get读不可用值时__set写不可用值时__isset对不可用值调用isset()empty()时__unset对不可用值调用unset()时__sleep序列化对象时__wakeup反序列化对象时__toString对象被作为字符串使用时__invoke尝试以调用函数方式调用对象时

示例

<?php
    class Test{
        public $a="aaa";
        private $b="bbb";
        protected $c=123;
        function __construct($a,$b,$c)
        {
            $this->a=$a;
            $this->b=$b;
            $this->c=$c;
            echo("Constructor called.<br>");
        }
        function __destruct()
        {
            echo("Destructor called.<br>");
        }
        function show()
        {
            echo($this->a."\n".$this->b."\n".$this->c."<br>");
        }
    }
    $data=new Test("a",1,1.1);
    $data_str=serialize($data);
    echo($data_str."\n");
    $data_new=unserialize($data_str);
    echo("<br>");
    $data_new->show();
?>

反序列化漏洞

反序列化漏洞指网站未对被用户所控制的序列化字符串做检查,攻击者提交了精心构造的有害序列化字符串,导致恶意代码被执行。常见于PHP、Python、Java等允许对象序列化功能的编程语言中。

在PHP中,导致反序列化漏洞的原因大多是魔术方法的不规范使用。(如输出变量内容、写文件操作、写数据库操作等参数用户可控)

构造函数&析构函数

假设网站页面部分代码编写如下:

<?php
    class Test
    {
        var $a="aaa";
        function __construct($a)
        {
            $this->a=$a;
            echo("Info:<br>".$a);
        }
    }
    $data_new=unserialize($_GET['data']);
    var_dump($data_new);
?>

当对象创建(或销毁)时,程序会输出对象中三个成员变量的值;程序还从API接口读取了一个序列化字符串并试图将其反序列化。此时如果将序列化字符串中的值修改为恶意代码,类名修改为Test,会导致反序列化漏洞攻击。

EXP:O:4:“Test”:1:{s:4:“test”;s:29:“<script>alert(‘xss’)</script>”;}

CVE-2016-7124

PHP5 <5.6.25PHP7 <7.0.10的环境中,如果类中存在__wakeup魔术方法,则在反序列化之前会先调用该方法。但当序列化字符串中属性数量大于真实属性数量时,该方法不会执行。

<?php
    class Test
    {
        var $mess="111";
        function __wakeup()
        {
            $this->mess="failed";
            echo("Please try again.<br>");
        }
    }
    $new_data=unserialize($_GET['ins']);
    var_dump($new_data);
?>

代码中,当反序列化一个字符串时,程序会执行__wakeup方法,将$mess设置为字符串,并显示失败信息。此时把序列化字符串中的属性数量值改大,__wakeup方法会失效。

EXP:http://127.0.0.1/serialize.php?ins=O:4:“Test”:2:{s:4:“mess”;s:25:"

<script>alert(1)</script>";}

到此这篇关于详解PHP反序列化漏洞示例与原理的文章就介绍到这了,更多相关PHP反序列化漏洞内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

上一篇:phpYii2框架创建定时任务方法详解
下一篇:没有了
网友评论