详解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:{…} 对象
N NULL

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反序列化漏洞内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解PHP反序列化漏洞的原理及示例

    目录 PHP反序列化 序列化与反序列化 PHP魔法函数 反序列化漏洞 简介 原理 触发条件 示例 PHP反序列化 序列化与反序列化 序列化说通俗点就是把一个对象变成可以传输的字符串.序列化过程中还会对不同属性的变量进行不同方式的变化 public的属性在序列化时,直接显示属性名 protected的属性在序列化时,会在属性名前增加0x00*0x00,其长度会增加3 private的属性在序列化时,会在属性名前增加0x00classname0x00,其长度会增加类名长度+2 反序列化就是把被序列化

  • PHP反序列化漏洞实例深入解析

    目录 引文 简介 基础知识 序列化 反序列化 属性 魔术方法 POP链 [MRCTF2020]Ezpop PHP字符串逃逸 结语 引文 上一篇给大家带来了XSS跨站脚本攻击漏洞不知道大家学的咋样了,今天给大家带来另一个漏洞,PHP的反序列化漏洞,这也是我在CTF比赛中遇到过最多的也是比较考察逻辑思维的一种漏洞. 简介 PHP反序列化是一个非常常见的漏洞,利用难度相比于文件上传等漏洞相对较困难,漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造

  • PHP的序列化和反序列化详情

    目录 一.PHP 为什么要反序列化? 二.PHP如何反序列化? 三.PHP反序列化漏洞 1.常用 的魔术方法 2.漏洞产生条件 3.题目 一.PHP 为什么要反序列化? PHP程序执行结束以后会将文件中的变量和内容释放掉, 如果一个程序想要的调用之前程序的变量,但是之前的程序已经执行完毕,所有的变量和内容都被释放,那该如何操作呢?这时候就可以通过序列化和反序列化保存程序中的对象,给其他程序使用. php序列化可以将对象转换成字符串,但只序列化属性,不序列化方法. 二.PHP如何反序列化? ​PH

  • PHP开发技巧之PHAR反序列化详解

    目录 引文 前置知识 PHAR PHAR文件结构 PHAR文件生成样例 实战 结语 引文 之前将PHP反序列化的基础知识讲了一遍,不知道大家学习的怎么样了,今天给大家带来PHP反序列化的进阶知识:PHAR反序列化,也是之前本人在CTF比赛中经常遇到的一种php反序列化的进阶使用吧,下面先给大家讲一讲PHAR反序列化的前置知识. 前置知识 PHAR 在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分

  • 深入浅析PHP的session反序列化漏洞问题

    在php.ini中存在三项配置项: session.save_path="" --设置session的存储路径 session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式) session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动 session.serialize_handler string --定义用来序列化/反序列化的处

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

    目录 预备知识 PHP序列化与反序列化 序列化字符串格式 PHP魔术方法 示例 反序列化漏洞 构造函数&析构函数 CVE-2016-7124 预备知识 PHP序列化与反序列化 序列化:将一个复杂的数据类型(如对象.数组.变量等)转换为字符串表示,以便于在网络中传输和在数据库中存储.在PHP语言中使用serialize()函数实现. 反序列化:将一个序列化的字符串重新转换为一个具体的数据类型.在PHP语言中使用unserialize()函数实现. PHP对象中只有数据会被序列化,方法不会被序列化.

  • 详解php反序列化

    1  前言 最近也是在复习之前学过的内容,感觉对PHP反序列化的理解更加深了,所以在此总结一下 2  serialize()函数 "所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字." 一开始看这个概念可能有些懵,但之后也是慢慢理解了 在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件.数据库是"持久数据",因此PHP序列

  • 详解Java volatile 内存屏障底层原理语义

    目录 一.volatile关键字介绍及底层原理 1.volatile的特性(内存语义) 2.volatile底层原理 二.volatile--可见性 三.volatile--无法保证原子性 四.volatile--禁止指令重排 1.指令重排 2.as-if-serial语义 五.volatile与内存屏障(Memory Barrier) 1.内存屏障(Memory Barrier) 2.volatile的内存语义实现 六.JMM对volatile的特殊规则定义 一.volatile关键字介绍及底

  • 详解Java线程池和Executor原理的分析

    详解Java线程池和Executor原理的分析 线程池作用与基本知识 在开始之前,我们先来讨论下"线程池"这个概念."线程池",顾名思义就是一个线程缓存.它是一个或者多个线程的集合,用户可以把需要执行的任务简单地扔给线程池,而不用过多的纠结与执行的细节.那么线程池有哪些作用?或者说与直接用Thread相比,有什么优势?我简单总结了以下几点: 减小线程创建和销毁带来的消耗 对于Java Thread的实现,我在前面的一篇blog中进行了分析.Java Thread与内

  • 详解vue的数据binding绑定原理

    自从angular火了以后,各种mvc框架喷涌而出,angular虽然比较火,但是他的坑还是蛮多的,还有许多性能问题被人们吐槽.比如坑爹的脏检查机制,数据binding是受人喜爱的,脏检查就有点-性能低下了.有时候改了一个地方,脏循环要循环多次来保证数据是不是真的变了和是否停止变化了.这样性能就很低了.于是人们开始钻研新的双向数据binding的方法.尤大的vue binding就是本人蛮喜欢的一种实现方式,本文跟随尤大的一个例子来详解vue的数据binding的原理. 数据binding,一般

  • 详解C++虚函数的工作原理

    静态绑定与动态绑定 讨论静态绑定与动态绑定,首先需要理解的是绑定,何为绑定?函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定. 理解了绑定后再理解静态与动态. 静态绑定:指在程序编译过程中,把函数调用与响应调用所需的代码结合的过程,称为静态绑定.发生在编译期. 动态绑定:指在执行期间判断所引用对象的实际类型,根据实际的类型调用其相应的方法.程序运行过程中,把函数调用与响应调用所需的代码相结合的过程称为动态绑定.发生于运行期. C++中动态绑定 在C++中动态绑定是通过虚函数

  • 详解SpringMVC的url-pattern配置及原理剖析

    xml里面配置标签: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> &

  • 详解ES6中class的实现原理

    一.在ES6以前实现类和继承 实现类的代码如下: function Person(name, age) { this.name = name; this.age = age; } Person.prototype.speakSomething = function () { console.log("I can speek chinese"); }; 实现继承的代码如下:一般使用原型链继承和call继承混合的形式 function Person(name) { this.name =

  • 详解Vue3 Teleport 的实践及原理

    Vue3 的组合式 API 以及基于 Proxy 响应式原理已经有很多文章介绍过了,除了这些比较亮眼的更新,Vue3 还新增了一个内置组件: Teleport.这个组件的作用主要用来将模板内的 DOM 元素移动到其他位置. 使用场景 业务开发的过程中,我们经常会封装一些常用的组件,例如 Modal 组件.相信大家在使用 Modal 组件的过程中,经常会遇到一个问题,那就是 Modal 的定位问题. 话不多说,我们先写一个简单的 Modal 组件. <!-- Modal.vue --> <

随机推荐