本文目录导读:

Java反序列化漏洞是Java安全领域最常见、危害最大的漏洞之一,攻击者通过发送恶意构造的序列化数据,可以在目标服务器上执行任意代码。
针对Java反序列化的防护,可以从代码层面、JVM层面、运维层面以及架构层面进行多层次的防御,以下是目前业界公认的有效防护措施:
白名单与黑名单机制(核心方案)
这是最直接、最有效的防护手段,通过限制允许反序列化的类来阻止恶意类的加载。
-
黑名单(极不推荐单独使用): 列出禁止反序列化的类。
- 缺点: 难以穷举所有恶意类(如CommonCollections、Fastjson、JNDI注入相关类等),攻防双方信息不对等,极易被绕过。
-
白名单(强烈推荐): 只允许反序列化业务中明确需要的类。
-
实现方式: 在自定义的
ObjectInputStream中重写resolveClass方法,对类名进行校验。 -
示例代码:
public class SafeObjectInputStream extends ObjectInputStream { private static final Set<String> WHITE_LIST = new HashSet<>(Arrays.asList( "com.example.User", "java.lang.String", "java.util.ArrayList" // ... 只添加你需要的类 )); @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className = desc.getName(); if (!WHITE_LIST.contains(className)) { throw new SecurityException("禁止反序列化非白名单类: " + className); } return super.resolveClass(desc); } }
-
使用安全的反序列化工具或替代方案
尽量避免使用Java原生的 ObjectInputStream,可以考虑以下替代方案:
- JSON 序列化: 使用
Jackson或Gson。- 注意: 即使使用JSON,也要注意
Fastjson的历史漏洞(需要开启autoType或SafeMode)以及Jackson的enableDefaultTyping导致的漏洞。
- 注意: 即使使用JSON,也要注意
- Protocol Buffers (Protobuf): Google出品,严格定义Schema,天然安全且高效。
- Kryo 或 Hessian: 如果必须使用二进制序列化,选择这些经过安全加固的库,并注意配置好类注册。
- Apache Avro / Thrift: 带有Schema定义的序列化框架。
升级依赖库与JDK版本
很多反序列化漏洞依赖于第三方库中的Gadget(利用链)。
- 及时打补丁: 关注并升级以下常见库的版本:
commons-collections(尤其是3.2.2及以上版本,有漏洞修复)commons-beanutilsspring-aopfastjson(保持最新或开启SafeMode)jackson-databindlog4j(Log4Shell后,新的利用链也存在)
- 升级JDK: 较新版本的JDK(如JDK 17+)默认限制了某些高危的JNDI远程类加载(
com.sun.jndi.ldap.object.trustURLCodebase默认设为false)。
运行时检测与防御
- 使用Java Agent工具: 如 RASP(Runtime Application Self-Protection)。
- 原理: RASP在JVM内部Hook(钩子)
resolveClass、readObject等关键方法,实时检测并拦截恶意类的加载或命令执行。 - 代表工具: OpenRASP(百度开源)。
- 原理: RASP在JVM内部Hook(钩子)
- SerialKiller(已过时,但思想值得参考): 通过配置拦截规则(正则表达式)来拒绝已知的恶意类,现代的RASP工具已基于更复杂的上下文判断。
JVM参数层面的防护(针对JNDI注入)
对于通过JNDI注入进行攻击的反序列化漏洞,JVM参数可以提供基础防护:
- JDK 8u191 之前版本:
- 设置
-Dcom.sun.jndi.ldap.object.trustURLCodebase=false(默认在新版本为false) - 设置
-Dcom.sun.jndi.rmi.object.trustURLCodebase=false
- 设置
- JDK 9+: 如果业务不需要,也可以显式设置以上参数为false。
架构层面的隔离与最小权限
- 最小化反序列化入口: 审查所有接收外部输入并进行反序列化的接口,如
RMI、HTTP Invoker、JMX、Session传输等,尽量用JSON替代这些接口。 - 网络隔离: 将反序列化接口(如RMI Service)放在内网,禁止对外暴露。
- 运行环境权限控制:
- 使用
SecurityManager(Java安全管理器)来限制代码权限(如禁止Runtime.exec、禁止读取敏感文件)。 - 注意:
SecurityManager在JDK 18中已被标记为弃用,未来版本可能移除,但仍是目前有效的加固手段。
- 使用
最佳实践流程
- 第一优先: 所有反序列化操作必须加入白名单,如果没有白名单,就相当于门没锁。
- 第二优先: 尽量用JSON/Protobuf替代Java原生序列化。
- 第三优先: 升级所有依赖库(重点:
commons-collections、fastjson、jackson)和JDK版本。 - 最后防线: 部署RASP(如OpenRASP)做运行时保护,监控是否存在未知漏洞的利用。
- 日常维护: 定期进行安全扫描(如使用OWASP Dependency Check)检查依赖库中的已知CVE(通用漏洞与暴露)。
一句话总结: 不要信任任何来自反序列化的数据,通过白名单强制约束可反序列化的类,并尽量使用更安全的序列化协议(如JSON/Protobuf)。