广告

Java序列化漏洞详解:原理、风险与防御方法的实战指南

1. 原理分析

Java 序列化的核心目标是将一个对象及其引用图写入字节流,以便在另一端重建。序列化过程将对象图转换为字节流,而反序列化则是从字节流还原对象图。

在实现上,Java 提供了 Serializable 接口、ObjectOutputStream 和 ObjectInputStream。序列化流包含元数据,如类描述和字段信息,以便正确还原对象类型。

1.1 机制要点

一个可序列化的类通常需要定义 serialVersionUID,确保版本兼容。serialVersionUID 用于版本控制,不匹配会导致 InvalidClassException。

此外,transient 字段不参与序列化,静态字段也不在对象图中;如果需要自定义序列化,可以实现 writeObject/readObject。

import java.io.*;// 安全示例:自定义反序列化时的校验
class User implements Serializable {private static final long serialVersionUID = 1L;String name;int age;private transient boolean valid;private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {ois.defaultReadObject();if (name == null || age < 0) {throw new InvalidObjectException("无效的数据");}valid = true;}
}

1.2 触发条件与执行流程

反序列化的风险在于 输入来自不受信任的来源时,如来自网络的字节流。如果序列化对象的类实现了自定义的 readObject/writeObject / readResolve,就可能在反序列化时执行额外逻辑。

Java序列化漏洞详解:原理、风险与防御方法的实战指南

在真实环境中,攻击者可能通过包含恶意对象图的序列化数据,触发代码路径,从而达到远程执行或崩溃等效果。不受保护的反序列化是常见的漏洞根源

2. 风险与攻击面

2.1 常见风险场景

在不可信数据进入反序列化逻辑时,远程代码执行(RCE)风险显著上升,攻击者可通过构造对象图触发恶意行为。

此外,还可能出现数据被篡改、对象状态被置换、服务宕机甚至造成更广的影响。数据完整性和系统稳定性受损

2.2 攻击向量概览

历史上,依赖库的 gadget 链(如 Commons Collections、Spring 对象)在反序列化时被利用,触发任意方法执行。攻击面与版本相关

现代应用还可能因为暴露的 RPC 接口、HTTP 接收器等,将<未验证的序列化数据作为输入进入反序列化路径。

2.3 现实环境中的教训

常见的失败原因包括:未禁用来自不可信源的反序列化、依赖库未打安全补丁、日志和缓存系统错误地处理序列化对象。定期升级依赖和启用防护策略至关重要

3. 防御方法与实战要点

3.1 基本安全原则

制定严格的安全策略,禁止对不可信输入进行直接反序列化,将反序列化与业务逻辑解耦。

优先采用<白名单,限制允许反序列化的类范围,减少潜在的攻击面。

3.2 使用对象输入过滤器 ObjectInputFilter

自 Java 9 及以上引入了 ObjectInputFilter,可以在反序列化阶段对类进行白名单过滤,阻断未知或不可信类的加载。

下面给出一个简化示例,展示如何在反序列化之前应用过滤规则。示例中的过滤器仅允许自家包名的类

import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;// 设置白名单过滤器(示例)
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(info -> {Class c = info.serialClass();if (c == null) return ObjectInputFilter.Status.UNDECIDED;String name = c.getName();if (name.startsWith("com.mycompany.")) {return ObjectInputFilter.Status.ACCEPTED;}return ObjectInputFilter.Status.REJECTED;
});

通过这样的过滤,阻止未知类进入反序列化流程,显著降低漏洞风险。

3.3 替代方案与安全改造

在可能的场景中,替换 Java 原生序列化为更安全的格式,如 JSON、XML、Protobuf、Avro 等,以及使用不可变对象模式。

对于网络 RPC,优先使用基于 HTTP/JSON 调用或消息队列传输的显式对象映射,避免直接暴露 Java 序列化入口。

3.4 监控、日志与应急

对反序列化相关的异常和警报进行集中日志,及时识别异常反序列化事件,并在必要时回滚或禁用相关接口。

确保依赖库有安全补丁并及时升级,并在 CI/CD 流水线中引入安全检查。

广告

后端开发标签