Java 反序列化漏洞
Java 反序列化漏洞详解
Java 反序列化漏洞(Java Deserialization Vulnerability)是 Java 应用中一种高危安全漏洞,曾导致多个重大安全事件(如 Apache Commons Collections 漏洞、WebLogic、Jenkins 等被攻破)。它允许攻击者通过构造恶意的序列化数据,在目标系统上执行任意代码(Remote Code Execution, RCE)。
一、什么是序列化与反序列化?
🔹 序列化(Serialization)
将 Java 对象转换为字节流,便于存储或网络传输。
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("obj.ser"));
out.writeObject(myObject);
out.close();
🔹 反序列化(Deserialization)
将字节流恢复为 Java 对象。
ObjectInputStream in = new ObjectInputStream(new FileInputStream("obj.ser"));
MyObject obj = (MyObject) in.readObject();
in.close();
⚠️ 问题出在
readObject()
:它会自动调用对象的构造函数、初始化方法,甚至触发恶意代码执行。
二、反序列化漏洞的原理
✅ 漏洞核心:
如果应用反序列化了不可信的数据(如用户输入、网络请求、文件上传),攻击者可以构造恶意对象,在反序列化过程中触发任意代码执行。
🔍 关键机制:readObject()
的自动调用
某些类在反序列化时会自动执行代码,例如:
java.util.PriorityQueue
org.apache.commons.collections.map.LazyMap
javax.management.BadAttributeValueExpException
这些类的 readObject()
方法在恢复对象时,会调用对象的 toString()
、equals()
、hashCode()
等方法。如果这些方法被恶意重写,就可能执行命令。
三、经典案例:Apache Commons Collections 漏洞(CVE-2015-4852)
这是最著名的 Java 反序列化漏洞之一。
攻击链(Gadget Chain)原理:
- 攻击者构造一个
LazyMap
对象,其transformer
是一个InvokerTransformer
,可执行任意方法。 - 将
LazyMap
放入HashMap
或PriorityQueue
。 - 当反序列化时,某些类(如
BadAttributeValueExpException
)会调用toString()
。 toString()
触发LazyMap.get()
→ 调用transformer.transform()
→ 执行Runtime.getRuntime().exec("malicious command")
🧨 结果:攻击者可在服务器上执行任意命令,如下载木马、提权、挖矿等。
四、反序列化漏洞的利用条件
条件 | 说明 |
---|---|
1. 应用使用 ObjectInputStream.readObject() | 常见于 RMI、JMX、Spring、Hibernate、Redis 存储对象等 |
2. 输入数据来自不可信源 | 如 HTTP 请求、文件上传、消息队列 |
3. 类路径中存在“利用链”(Gadget Chains) | 如 Apache Commons Collections、Groovy、Jython 等第三方库 |
五、常见攻击场景
场景 | 说明 |
---|---|
RMI(Remote Method Invocation) | RMI 服务默认使用 Java 序列化,易受攻击 |
JMX(Java Management Extensions) | JMX 接口暴露时可能被利用 |
Spring 框架 | Spring 某些组件(如 Spring REST)支持序列化对象传输 |
Redis / Memcached 存储 Java 对象 | 如果反序列化缓存对象,可能被注入 |
文件上传反序列化 | 用户上传 .ser 文件,服务器读取 |
六、如何检测反序列化漏洞?
✅ 1. 代码审计
查找是否使用:
ObjectInputStream.readObject();
ObjectInputStream.readUnshared();
✅ 2. 依赖检查
检查 pom.xml
或 build.gradle
是否包含:
commons-collections:commons-collections
groovy
,jython
,xstream
等存在 gadget 的库
✅ 3. 使用工具扫描
- ysoserial:生成恶意 payload 的工具(用于测试)
- Burp Suite + Java Deserialization Scanner 插件
- Checkmarx、Fortify 等 SAST 工具
七、防御措施(最佳实践)
✅ 1. 避免反序列化不可信数据
- 不要从网络、文件、用户输入中反序列化对象
- 使用 JSON、XML 等数据格式替代
✅ 2. 使用 serialVersionUID
并校验完整性
private static final long serialVersionUID = 123456789L;
但不能防止恶意对象,仅防版本错乱。
✅ 3. 自定义 readObject()
方法
在敏感类中重写 readObject()
,加入校验逻辑:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();// 添加校验if (this.username == null || this.username.contains(";")) {throw new InvalidObjectException("Invalid input");}
}
✅ 4. 使用 ObjectInputFilter
(Java 9+)
限制可反序列化的类:
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filterInfo -> {if (filterInfo.serialClass() == null) return -1;String name = filterInfo.serialClass().getName();if (name.equals("com.example.TrustedClass")) {return 1;}return -1; // 拒绝其他类
});
✅ 5. 使用安全的替代序列化方式
- JSON:Jackson、Gson
- Protobuf:Google Protocol Buffers
- Kryo(需配置安全反序列化)
- MessagePack
✅ 6. 升级依赖库
- 升级
commons-collections
到 3.2.2+ 或 4.1+ - 使用最新版本的 Spring、Hibernate 等框架
✅ 7. 启用 WAF 或 IPS 防护
- 配置 Web 应用防火墙(如 ModSecurity)检测恶意序列化特征
- 使用 RASP(运行时应用自我保护)工具
八、真实漏洞案例
漏洞 | 影响产品 | CVSS 评分 |
---|---|---|
CVE-2015-4852 | Apache Commons Collections | 9.8(Critical) |
CVE-2017-3241 | Oracle WebLogic RMI | 9.8 |
CVE-2016-4437 | JBoss Marshalling | 9.8 |
CVE-2020-2551 | Oracle Coherence | 9.8 |
✅ 总结
问题 | 回答 |
---|---|
什么是 Java 反序列化漏洞? | 攻击者通过构造恶意序列化数据,在反序列化时执行任意代码 |
危害是什么? | 远程代码执行(RCE),服务器被完全控制 |
常见利用链? | Commons Collections、Groovy、Jython 等 |
如何防御? | 1. 避免反序列化不可信数据 2. 使用 ObjectInputFilter 3. 升级依赖 4. 使用 JSON 等安全格式 |
📌 一句话总结:
Java 反序列化漏洞是“信任字节流”的代价——永远不要反序列化不可信的数据,否则你的服务器就是攻击者的“命令行”。