彻底防止java反序列化rce的关键是切断恶意链触发路径,需分层阻断:严格启用objectinputfilter白名单、禁用危险类与系统调用、根本性迁移到json/grpc等安全格式,并辅以运行时监控与依赖扫描。

彻底防止Java反序列化引发的远程代码执行(RCE),关键不是“加固readObject”,而是**切断恶意链的触发路径**。只要反序列化流程允许任意类加载和方法调用,再严密的校验都可能被绕过。真正有效的防护是分层阻断、源头规避。
严格启用 ObjectInputFilter 白名单机制
Java 9+ 原生支持序列化过滤器,这是目前最可靠、最轻量的运行时防护手段。它在反序列化开始前就拦截非法类,不依赖开发者手动检查字段或逻辑。
- 必须在创建 ObjectInputStream 实例前设置过滤器,例如:
ObjectInputStream ois = new ObjectInputStream(inputStream);<br>ois.setObjectInputFilter(createFilter());
- 白名单规则应精确到具体类名,避免通配符滥用(如
com.example.*可能放行攻击者构造的子类);推荐写成java.util.ArrayList;com.myapp.User;com.myapp.Order - 可配合 JVM 启动参数全局启用:
-Djdk.serialFilter="maxdepth=10;maxarray=100000;deny=org.apache.commons.collections.*",但生产环境仍建议代码级显式配置,避免参数遗漏
禁止反序列化过程中触发危险行为
即使类在白名单中,其自定义 readObject() 或静态初始化块仍可能执行命令。需从JVM层面封堵执行通道:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 禁用 Runtime.exec、ProcessBuilder.start 等系统调用:通过自定义 SecurityManager 拦截
java.io.FilePermission(">", "execute")和java.lang.RuntimePermission("exec") - 注意:Java 17+ 默认移除了 SecurityManager,若无法升级,可用字节码插桩(如 Byte Buddy)或 JVM Agent(如 OpenTelemetry)在方法入口处动态注入检查逻辑
- 对已知高危类(如
javax.management.BadAttributeValueExpException、org.apache.commons.collections.Transformer)直接加入黑名单过滤器,双重保险
根本性规避:停用原生序列化,改用安全格式
白名单和权限控制仍是“带锁的门”,而换格式是“拆掉那扇门”。只要业务不强依赖 Java 原生对象图还原,就应主动迁移:
- 用 JSON(Jackson / Gson) 替代二进制序列化:它天然不执行代码、不还原类结构,只解析为 Map 或 DTO 对象;务必关闭 Jackson 的
enableDefaultTyping(),禁用自动类型推断 - RPC 场景优先选用 gRPC + Protobuf:协议严格定义 schema,无反射、无动态类加载,序列化过程完全可控
- 缓存场景避免存
Serializable对象:改用 JSON 字符串 + TTL 控制,或使用 Redis 的 Hash 结构按字段存储,彻底绕开反序列化环节
运行时加固与监控兜底
防御不能只靠编码规范,需建立可观测防线:
- 在所有
ObjectInputStream.readObject()调用点统一封装工具类,强制校验输入流来源(如仅允许来自内部 RPC 通道,拒绝 HTTP Body 或 Cookie) - 日志记录每次反序列化的类名、调用栈、线程ID;当检测到非白名单类或高频失败尝试时,触发告警并熔断该请求链路
- 定期扫描 classpath 中是否存在已知 gadget 库(如 Commons Collections 3.1/4.0、Groovy 2.3.x),及时升级或排除——很多 RCE 利用链依赖特定版本的反射链
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










