核心是阻断恶意字节流进入反序列化流程,而非拦截gadget链:禁用原生序列化,改用json/protobuf等结构化格式;启用jdk序列化过滤器并严格白名单;重写resolveclass()限制可加载类;升级加固第三方库如commons collections、jackson和fastjson。

避免 gadget 链触发远程代码执行,核心不是“拦住某个链”,而是让恶意字节流根本走不到能触发链的位置。关键在于切断攻击路径的每个环节,而不是等它跑起来再拦截。
禁用原生序列化对外暴露
最彻底的办法是不让 ObjectInputStream 出现在可信边界之外。Web 接口、RPC 通信、缓存数据、消息队列 payload —— 这些场景一律改用 JSON(Jackson/Gson)、Protobuf 或 Avro。它们只解析结构化数据,不执行任意方法,天然免疫 gadget 链。
- Spring Boot 项目中,把所有 @RequestBody 的反序列化逻辑从 ObjectInputStream 切换为 Jackson;
- Redis 缓存对象时,不用 Java 原生序列化,改用 StringRedisTemplate + JSON 序列化器;
- 内部 RPC 若必须二进制,优先选 gRPC(基于 Protobuf),而非基于 Java 序列化的老框架。
强制启用并收紧 JDK 级过滤器
JDK 9+ 提供的 ObjectInputFilter 是基础防线,但默认不启用,且宽松配置等于没设。必须显式声明白名单,并限制深度与大小:
- 启动参数加:-Djdk.serialFilter="maxdepth=3;maxarray=10000;java.lang.String;java.util.ArrayList;java.time.*;!";
- 代码中显式设置:
ois.setObjectInputFilter(FilterBuilder.create("java.lang.*;java.util.*;!"));; - 禁止通配符泛滥,比如
com.example.**会放行所有子包,包括未来引入的含 gadget 的第三方类。
白名单驱动的类加载控制
仅靠 filter 不够,因为攻击者可能绕过它直接调用 resolveClass()。更稳妥的做法是继承 ObjectInputStream,重写 resolveClass(),只允许极少数安全类型:
- 明确列出可反序列化的类名(如
java.lang.Integer、com.myapp.dto.UserDTO); - 拒绝所有未注册类,抛出
ClassNotFoundException; - 避免在白名单里包含
org.apache.commons.collections、javax.management、sun.reflect等高危包。
清理和加固第三方依赖
很多 gadget 链来自第三方库,防御不能只靠拦截,更要从源头消除风险:
- 升级 Apache Commons Collections 到 4.4+(已移除危险 Transformer 类);
- Jackson 中禁用
enableDefaultTyping(),改用@JsonTypeInfo显式声明多态类型; - Fastjson 设置
ParserConfig.getGlobalInstance().setAutoTypeSupport(false); - 定期扫描依赖树(如用
mvn dependency:tree或 Snyk),剔除含已知 gadget 的旧版本库。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











