PHP反序列化漏洞这么学(细)!
字数 1623 2025-08-09 22:00:40

PHP反序列化漏洞深入解析

一、PHP序列化与反序列化基础

1.1 序列化概念

序列化是将对象转换为可存储或传输的字符串的过程,反序列化则是将字符串重新转换为对象。

1.2 PHP序列化函数

  • serialize() - 将对象序列化为字符串
  • unserialize() - 将字符串反序列化为对象

1.3 序列化格式

PHP序列化字符串格式示例:

O:4:"User":2:{s:4:"name";s:5:"admin";s:6:"isAdmin";b:1;}

解释:

  • O:4:"User" - 对象,类名长度为4,类名为"User"
  • 2 - 对象有2个属性
  • s:4:"name" - 字符串属性,长度4,名称为"name"
  • s:5:"admin" - 字符串值,长度5,值为"admin"
  • s:6:"isAdmin" - 字符串属性,长度6,名称为"isAdmin"
  • b:1 - 布尔值,值为true

二、PHP反序列化漏洞原理

2.1 漏洞产生条件

  1. 应用程序接收用户可控的反序列化数据
  2. 目标类中存在"魔法方法"
  3. 类属性可用于危险操作

2.2 危险魔法方法

  • __wakeup() - 反序列化时自动调用
  • __destruct() - 对象销毁时调用
  • __toString() - 对象被当作字符串使用时调用
  • __call() - 调用不可访问方法时触发

2.3 攻击面

攻击者可以:

  1. 控制反序列化的类
  2. 控制类属性值
  3. 触发危险方法执行恶意代码

三、漏洞利用技术

3.1 基本利用流程

  1. 寻找包含魔法方法的类
  2. 分析类中危险操作
  3. 构造恶意序列化字符串
  4. 触发反序列化操作

3.2 实例分析

class Example {
    public $file;
    public $data;
    
    public function __destruct() {
        file_put_contents($this->file, $this->data);
    }
}

// 恶意序列化数据
$payload = serialize(new Example());
$payload = str_replace(
    'O:7:"Example":2:{s:4:"file";N;s:4:"data";N;}',
    'O:7:"Example":2:{s:4:"file";s:8:"test.php";s:4:"data";s:18:"<?php phpinfo(); ?>";}',
    $payload
);

// 触发漏洞
unserialize($payload);

3.3 属性数量不一致攻击

PHP 5.6.30之前存在CVE-2016-7124漏洞,当序列化字符串中表示对象属性个数的值与实际属性个数不一致时,可以绕过__wakeup()的执行。

利用方式:

O:4:"User":1:{s:4:"name";s:5:"admin";}
改为
O:4:"User":100:{s:4:"name";s:5:"admin";}

四、POP链构造

4.1 概念

Property-Oriented Programming(面向属性编程),通过组合多个类的魔法方法形成攻击链。

4.2 构造步骤

  1. 寻找起点(如__destruct()
  2. 寻找数据传输点(类属性)
  3. 寻找危险函数调用点
  4. 连接各点形成完整利用链

4.3 实例分析

class FileClass {
    public $filename;
    
    public function __toString() {
        return file_get_contents($this->filename);
    }
}

class User {
    public $obj;
    
    public function __destruct() {
        echo $this->obj;
    }
}

// 构造POP链
$file = new FileClass();
$file->filename = '/etc/passwd';

$user = new User();
$user->obj = $file;

$payload = serialize($user);
unserialize($payload);

五、防御措施

5.1 输入验证

  • 不要反序列化不可信数据
  • 使用JSON等更安全的数据交换格式

5.2 安全配置

  • 升级PHP版本(修复已知漏洞)
  • 禁用危险函数(如unserialize()

5.3 代码层面

  1. 限制魔法方法的敏感操作
  2. 对反序列化类进行白名单控制
  3. 使用__wakeup()重置对象状态

5.4 加密签名

对序列化数据进行签名,确保数据未被篡改

六、实战案例分析

6.1 Typecho反序列化漏洞

  1. 漏洞点:install.php中的反序列化操作
  2. 利用链:通过__get()方法触发文件包含
  3. 最终实现远程代码执行

6.2 ThinkPHP反序列化漏洞

  1. 利用__destruct()方法
  2. 通过__toString()触发文件操作
  3. 结合其他功能实现完整利用

七、工具与资源

7.1 工具推荐

  • PHPGGC - PHP反序列化payload生成工具
  • php-serialize - PHP序列化分析工具
  • Burp Suite - 用于拦截和修改序列化数据

7.2 学习资源

  • PHP官方文档(序列化部分)
  • OWASP反序列化备忘单
  • 已知PHP反序列化漏洞CVE分析

八、高级技巧

8.1 字符逃逸

利用序列化字符串的格式特点,通过精心构造数据改变解析逻辑

8.2 引用攻击

利用PHP对象引用特性,修改已序列化对象的属性

8.3 Phar反序列化

通过Phar文件的元数据触发反序列化操作,扩展攻击面

九、总结

PHP反序列化漏洞危害严重,开发人员应:

  1. 避免反序列化用户输入
  2. 谨慎实现魔法方法
  3. 保持PHP环境更新
  4. 实施深度防御策略

安全研究人员应:

  1. 深入理解序列化机制
  2. 掌握POP链构造方法
  3. 关注新型利用技术
  4. 负责任地披露漏洞
PHP反序列化漏洞深入解析 一、PHP序列化与反序列化基础 1.1 序列化概念 序列化是将对象转换为可存储或传输的字符串的过程,反序列化则是将字符串重新转换为对象。 1.2 PHP序列化函数 serialize() - 将对象序列化为字符串 unserialize() - 将字符串反序列化为对象 1.3 序列化格式 PHP序列化字符串格式示例: 解释: O:4:"User" - 对象,类名长度为4,类名为"User" 2 - 对象有2个属性 s:4:"name" - 字符串属性,长度4,名称为"name" s:5:"admin" - 字符串值,长度5,值为"admin" s:6:"isAdmin" - 字符串属性,长度6,名称为"isAdmin" b:1 - 布尔值,值为true 二、PHP反序列化漏洞原理 2.1 漏洞产生条件 应用程序接收用户可控的反序列化数据 目标类中存在"魔法方法" 类属性可用于危险操作 2.2 危险魔法方法 __wakeup() - 反序列化时自动调用 __destruct() - 对象销毁时调用 __toString() - 对象被当作字符串使用时调用 __call() - 调用不可访问方法时触发 2.3 攻击面 攻击者可以: 控制反序列化的类 控制类属性值 触发危险方法执行恶意代码 三、漏洞利用技术 3.1 基本利用流程 寻找包含魔法方法的类 分析类中危险操作 构造恶意序列化字符串 触发反序列化操作 3.2 实例分析 3.3 属性数量不一致攻击 PHP 5.6.30之前存在 CVE-2016-7124 漏洞,当序列化字符串中表示对象属性个数的值与实际属性个数不一致时,可以绕过 __wakeup() 的执行。 利用方式: 四、POP链构造 4.1 概念 Property-Oriented Programming(面向属性编程),通过组合多个类的魔法方法形成攻击链。 4.2 构造步骤 寻找起点(如 __destruct() ) 寻找数据传输点(类属性) 寻找危险函数调用点 连接各点形成完整利用链 4.3 实例分析 五、防御措施 5.1 输入验证 不要反序列化不可信数据 使用JSON等更安全的数据交换格式 5.2 安全配置 升级PHP版本(修复已知漏洞) 禁用危险函数(如 unserialize() ) 5.3 代码层面 限制魔法方法的敏感操作 对反序列化类进行白名单控制 使用 __wakeup() 重置对象状态 5.4 加密签名 对序列化数据进行签名,确保数据未被篡改 六、实战案例分析 6.1 Typecho反序列化漏洞 漏洞点: install.php 中的反序列化操作 利用链:通过 __get() 方法触发文件包含 最终实现远程代码执行 6.2 ThinkPHP反序列化漏洞 利用 __destruct() 方法 通过 __toString() 触发文件操作 结合其他功能实现完整利用 七、工具与资源 7.1 工具推荐 PHPGGC - PHP反序列化payload生成工具 php-serialize - PHP序列化分析工具 Burp Suite - 用于拦截和修改序列化数据 7.2 学习资源 PHP官方文档(序列化部分) OWASP反序列化备忘单 已知PHP反序列化漏洞CVE分析 八、高级技巧 8.1 字符逃逸 利用序列化字符串的格式特点,通过精心构造数据改变解析逻辑 8.2 引用攻击 利用PHP对象引用特性,修改已序列化对象的属性 8.3 Phar反序列化 通过Phar文件的元数据触发反序列化操作,扩展攻击面 九、总结 PHP反序列化漏洞危害严重,开发人员应: 避免反序列化用户输入 谨慎实现魔法方法 保持PHP环境更新 实施深度防御策略 安全研究人员应: 深入理解序列化机制 掌握POP链构造方法 关注新型利用技术 负责任地披露漏洞