1、概述
反序列化漏洞是指在系统或应用程序接受序列化字符串进行解析时处理不当引发的安全漏洞。知名的有
- Java反序列化漏洞
- PHP反序列化漏洞
- fastjson反序列化漏洞
- .NET反序列化漏洞
反序列化和序列化是相对应的,序列化是将对象的状态信息转换为可以储存或传输的形式(字节序列)的过程,而反序列化是将序列化的字节序列还原成对象的过程。
Java语言中主要是:
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject
PHP语言中主要是
serialize()
unserialize()
2、漏洞原理+利用
2.1、Java
原理: 暴露或间接暴露反序列化 API ,导致用户可以操作传入数据,攻击者可以精心构造反序列化对象并执行恶意代码
两个或多个看似安全的模块在同一运行环境下,共同产生的安全问题 。
利用: 使用现有工具
2.2、PHP
原理: 当进行PHP反序列化操作时,如果传入了关于类的对象,会自动调用该类的一些方法,如:__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(),__sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone(), and __autoload() 从而导致意外地执行了某些代码。
利用:
3、漏洞挖掘
3.1、Java
- 从流量中发现序列化的痕迹,关键字:
ac ed 00 05
,rO0AB
- Java RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是
1099
端口 - 从源码入手,可以被序列化的类一定实现了
Serializable
接口 - 观察反序列化时的
readObject()
方法是否重写,重写中是否有设计不合理,可以被利用之处
3.2、PHP
- PHP序列化字符串格式说明
这段PHP代码演示了一个对象的序列化过程,生成了包含不同数据类型的对象,并展示了其序列化后的字符串表示形式。
- 序列化字符串示例
O:6:"ClassA":5:{
s:3:"int";i:1;
s:3:"str";s:5:"Hello";
s:4:"bool";b:0;
s:3:"obj";r:1;
s:2:"pr";R:3;
}
- 序列化标识符解释
O: 表示类对象,后跟类名和属性数量。
s: 表示字符串,后跟字符串长度和内容。
i: 表示整数。
b: 表示布尔值。
r: 表示引用的序列化标识符。
R: 表示指针引用的序列化标识符
4、漏洞防御
- 不信任用户输入: 不要直接反序列化从不可信源接收的数据。确保只从可信任的源获取并处理反序列化数据。
- 数据验证: 在反序列化之前对输入数据进行验证,确保它符合预期的格式和结构。使用强制数据验证来确保只有合法的数据被反序列化。
- 使用白名单机制: 限制允许反序列化的类和对象。使用白名单机制,只允许反序列化预定义的类,防止攻击者注入恶意类。
- 使用安全的序列化库: 选择使用安全的序列化库,这些库可能提供了一些内置的安全功能,如防止一些类型的攻击。
- 最小权限原则: 尽量以最小的权限运行反序列化操作。限制反序列化过程的访问权限,以减少潜在的攻击面。
- 监控和日志: 实施详细的监控和日志记录,以便及时检测到任何不寻常的反序列化操作或异常情况。
- 更新和维护: 及时更新和维护相关库和框架,因为厂商可能会发布修复安全漏洞的更新。
- 使用安全编码实践: 遵循安全的编码实践,包括输入验证、错误处理和异常处理,以提高应用程序的整体安全性。