flawopen.com/Java 反序列化/ObjectInputStream 安全
ObjectInputStream 能安全处理不可信数据吗?
Java 安全参考
通俗解释
通常不安全:readObject() 会重建 Java 对象,并可能调用类定义的反序列化方法。就像接收一份表单,却允许附件执行自带指令。恶意数据流可能触发应用中已有类的行为。是否执行代码取决于类、依赖库、可达路径和输入边界;并非每次调用都会触发。
有风险:原生对象反序列化
// 不要在此传入攻击者可控字节。
try (var in = new ObjectInputStream(untrustedStream)) {
Object value = in.readObject();
handle(value);
}
更安全:解析固定数据类型
// 对不可信输入关闭宽泛多态类型机制。
ObjectMapper mapper = new ObjectMapper();
OrderRequest value = mapper.readValue(
untrustedBytes, OrderRequest.class
);
validate(value);
缺陷如何变得可达
API、队列、缓存或文件导入接收了用户可控字节。字节到达 ObjectInputStream.readObject() 后,JVM 会恢复进程中的可序列化类对象。gadget 链只是通过这些类行为的一种可能路径,并非每个数据流都有特殊载荷。Oracle 在 CVE-2015-4852 中记录了特定案例:针对所列版本通过 WebLogic T3 发起未认证网络攻击。这不表示所有 ObjectInputStream 用法都可远程触达。
若无法移除原生序列化
- ✓优先使用带显式模式的 JSON 或 Protocol Buffers,映射到固定 DTO 后验证字段和授权。
- ✓若不可避免,在
readObject()前配置上下文专用ObjectInputFilter,只允许该数据流确需的类。 - ✓根据有效输入限制深度、引用数、数组和数据流字节。类白名单本身无法阻止资源耗尽。
- ✓不要为不可信 JSON 启用宽泛多态类型;任意子类型元数据可能重新导致对象构造。
- ✓更新 Java 和依赖,删除无用库,并以最小权限和资源限制处理旧数据流。
常见问题
ObjectInputFilter 能让 readObject() 安全吗?
窄范围白名单和读取前资源限制能降低风险,但它不是通用净化器。允许的类、其行为和过滤器是否实际生效都很重要;应用验证与授权仍不可少。尽可能避免对用户控制数据使用原生序列化。