Java反序列化漏洞防御需结合SecurityManager策略文件与jdk.serialFilter白名单双重控制:前者限制反序列化后危险操作权限,后者在类加载前拦截恶意类;同时应禁用RMI/JMX等自动反序列化入口,并覆写resolveClass做业务层校验。

Java 中反序列化默认不校验数据来源,攻击者可构造恶意字节流触发任意代码执行。要限制不受信任的代码执行,需结合 安全策略文件(policy file) 与 反序列化过滤机制 双重控制,而非仅靠策略文件单独拦截——因为 SecurityManager 对 ObjectInputStream.readObject() 本身无直接权限检查,它主要约束反射、文件读写、网络连接等底层操作。
启用安全管理器并加载自定义策略
策略文件不能阻止反序列化动作本身,但能限制反序列化后对象在初始化或方法调用时所需的危险权限。必须显式启用 SecurityManager 并指定 policy 文件:
- 启动 JVM 时添加参数:
java -Djava.security.manager -Djava.security.policy=conf/my.policy MyApp -
my.policy中至少禁用关键高危权限,例如:grant { // 禁止执行系统命令(防止 Runtime.exec、ProcessBuilder) permission java.lang.RuntimePermission "executeCommand"; // 禁止动态加载类或访问内部 API(削弱 gadget 链利用) permission java.lang.RuntimePermission "getClassLoader"; permission java.lang.RuntimePermission "setSecurityManager"; // 禁止文件读写(防止读取敏感配置或写入 WebShell) permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete"; // 禁止网络连接(阻断外连回传、DNSLog 等) permission java.net.SocketPermission "*", "connect,resolve"; };
强制启用反序列化白名单过滤器
Java 9+ 提供 jdk.serialFilter 系统属性,是真正拦截恶意类加载的核心手段。策略文件需配合该机制才有效:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 在 JVM 启动参数中设置白名单(推荐):
-Djdk.serialFilter="maxdepth=5;maxarray=100000;pattern=java.util.ArrayList;pattern=java.lang.String;pattern=com.example.model.*" - 或在
java.security配置文件中全局声明:jdk.serialFilter=maxdepth=5;maxarray=100000;pattern=java.base/*;pattern=java.desktop/*;pattern=com.myapp.dto.* - 注意:黑名单模式(如
!org.apache.commons.collections)已被证明不可靠,应避免使用
在 ObjectInputStream 子类中主动校验类名
策略文件和系统属性是全局控制,但业务层需做最后一道防线。建议继承 ObjectInputStream,覆写 resolveClass 方法:
立即学习“Java免费学习笔记(深入)”;
- 只允许加载预定义包路径下的类,拒绝
org.springframework、com.sun、groovy等高危 gadget 包 - 示例逻辑:
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); if (!name.startsWith("java.") && !name.startsWith("javax.") && !name.startsWith("com.myapp.")) { throw new InvalidClassException("Unauthorized class: " + name); } return super.resolveClass(desc); }
禁用不安全的反序列化入口点
很多漏洞并非来自 ObjectInputStream,而是框架自动反序列化(如 RMI、JMX、Spring HTTP Invoker)。应从源头关闭:
- RMI:设置
sun.rmi.transport.tcp.handshakeTimeout=0或禁用非必要注册表 - JMX:启动时加
-Dcom.sun.management.jmxremote.authenticate=true并关闭匿名访问 - Spring Boot:移除
spring-boot-starter-remote-shell,禁用spring.jackson.deserialization.use-typed-streams=false - 明确禁止使用
URLClassLoader、Reflections等动态加载类的工具处理反序列化结果

















