悠悠楠杉
Java序列化与反序列化安全漏洞深度解析(权威指南)
一、序列化:便捷背后的危险陷阱
Java序列化(Serialization)作为对象持久化的核心机制,通过Serializable
接口实现对象到字节流的转换。开发者在远程通信(RMI)、缓存存储等场景中频繁使用,但鲜少意识到其暗藏杀机:
java
// 典型序列化代码
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"))) {
oos.writeObject(user); // User类实现了Serializable
}
当反序列化(Deserialization)执行时,JVM会自动调用对象的readObject()
方法——这正是攻击者的突破口。漏洞本质在于:反序列化过程会执行类路径中任意可用的构造函数和方法。
二、漏洞原理:攻击链如何形成
2.1 关键攻击路径
- 恶意对象构造:攻击者伪造包含危险代码的序列化数据
- 危险方法调用:利用类库中的反射、动态代理等机制(如
InvokerTransformer
) - RCE达成:通过调用
Runtime.exec()
等执行系统命令
以经典的Apache Commons Collections漏洞为例:
java
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"})
};
2.2 漏洞利用三要素
- 存在危险类(如
AnnotationInvocationHandler
) - 反序列化入口点(如HTTP参数接收)
- 类加载路径可控(攻击者能上传恶意类)
三、企业级防护方案实战
3.1 白名单校验(推荐)
java
public class SecureObjectInputStream extends ObjectInputStream {
private static final Set
Set.of("com.domain.User", "java.util.ArrayList");
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized class", desc.getName());
}
return super.resolveClass(desc);
}
}
3.2 其他防护手段
- JEP 290机制(JDK9+)
bash -Djdk.serializationFilter=pattern
- 替换序列化协议
- JSON(Jackson/Gson)
- Protocol Buffers
- 运行时防护
- 启用SecurityManager
- 使用Java Agent监控可疑调用
四、历史重大漏洞启示录
| 漏洞名称 | 影响范围 | CVSS评分 |
|---------------------------|--------------------|----------|
| Apache Commons Collections | 影响70% Java应用 | 9.8 |
| Spring AMQP反序列化 | Spring框架生态 | 8.1 |
| JBoss JMXInvokerServlet | 旧版中间件系统 | 7.5 |
这些案例证明:只要存在反序列化入口点+类路径可控,就存在被攻破的可能。
五、安全开发规范建议
代码层面
- 禁止反序列化不可信数据
- 所有序列化类添加
serialVersionUID
- 敏感字段标记
transient
架构层面
- 网络边界部署WAF过滤ACED0005等魔数
- 微服务间改用签名校验的JSON通信
监控层面
java // 示例:日志监控异常反序列化 if (e instanceof InvalidClassException) { securityAlert.send("Potential exploit attempt"); }
专家建议:在金融等高安全场景,应当彻底禁用Java原生序列化,采用加密签名机制的二进制协议(如ASN.1)。