dinosn/fastjson-jsontype-rce-lab
A dual-track research lab reconstructing Fastjson RCE chains: a legacy JDK 8 direct-remote-class JSONType RCE for Fastjson 1.2.83, and a modern JDK 17 retained-JAR via proc-self-fd composition that works even with AutoType disabled and DTO binding in place, exploiting how ParserConfig.checkAutoType probes every type value via getResourceAsStream. It also reproduces an independent fastjson2 2.0.57/2.0.62 autoType bypass disclosed by Chaitin, where ObjectReaderSeeAlso hardcodes SupportAutoType, letting seeAlso/JsonSubTypes/sealed-type modeling trigger remote class loading even with autoType disabled. The repo ships dependency-free Python scanner tools for passive log detection, static artifact inventory, and safe active reachability probing via Burp Collaborator or interactsh.
What it is
Companion lab reproducing the Fastjson 1.2.83 RCE chain disclosed by Kirill Firsov (FearsOff, July 21 2026), with a modern-JDK reconstruction in modern-fd/ (Spring Boot 3, embedded Tomcat, JDK 17), a legacy command-capable Docker Compose lab for the JDK 8 direct-remote-class route, and an independent fastjson2 2.0.57/2.0.62 autoType bypass disclosed by Chaitin (~2026-07-25).
How it works
ParserConfig.checkAutoType probes every @type value via getResourceAsStream(typeName.replace('.','/') + ".class"). On modern Linux/JDK, a jar:http: probe can leave the fetched JAR cached behind an open file descriptor; a later jar:file:/proc/self/fd/N probe in the same request body reopens it under a valid class name and initializes an @JSONType-annotated class. This works through a fixed DTO (JSON.parseObject(body, BoundEnvelope.class)) with AutoType disabled — binding alone doesn't stop it. In the legacy JDK 8 lab, the attacker class's <clinit> runs during the @type probe, before fastjson even attempts the cast (visible as ClassCastException after the command already ran).
The independent fastjson2 bug is unrelated to this resource probe: ObjectReaderSeeAlso's constructor hardcodes SupportAutoType, so any polymorphic-type annotation (@JSONType(seeAlso=), Jackson @JsonSubTypes, @JsonTypeInfo, sealed types) falls through to full autoType resolution and class loading even with autoType disabled.
Preconditions / Affected
- Modern chain: Fastjson 1.2.83, fixed-DTO parsing, AutoType disabled — JDK 17 lane proven here; FearsOff separately reports a JDK 21 variant (not reproduced in this repo).
- fastjson2 bug: 2.0.57/2.0.62 on JDK 8 triggers full RCE; JDK 17 downgrades it to SSRF only;
safeMode=trueblocks it;autoTypeFilter(...)does not protect. - Legacy JDK 8 route is command-capable (writes to
/tmp/PWNED) and must stay isolated.
What to do
Reproduce the modern lab:
cd modern-fd
./scripts/static-safety-check.sh
./scripts/run-positive.sh
./scripts/run-controls.shLegacy lab (isolated only):
make up
make exploit
make downScanning tools (dependency-free Python 3):
python3 scanner/fjdetect.py --ndjson gateway.jsonl
python3 scanner/fjscan_static.py /path/to/artifacts --threads 16
python3 scanner/fjscan_probe.py --collaborator <sub>.oastify.com --auto --targets domains.txt --threads 50
python3 scanner/fjpayload.py <collab-or-ip> --targets-file domains.txtMitigations stated: enable -Dfastjson.parser.safeMode=true, or use com.alibaba:fastjson:1.2.83_noneautotype; audit installed AutoTypeCheckHandlers; restrict JVM egress; migrate off Fastjson 1.x; alert on decoded @type remote-JAR seeds and /proc/self/fd or /dev/fd candidates within one request and correlated across requests. For fastjson2, a maintainer fix in PR #7703 (rejecting : and ! in type names) is open but unreleased — 2.0.62 predates it.
Caveats
- Dotted Collaborator subdomains (
abc.oastify.com) can't be delivered through the@JSONTypejar sink (dots become slashes); tools fall back to--probe-type dnsagainstInet4Address, which only confirms egress/parsing, not the remote-JAR/FD terminal. - Alibaba's advisory reports broader version/runtime coverage (1.2.68–1.2.83, Spring Boot 2.x–4.x, JDK 8/11/17/21); this repo's actual runtime proof is limited to 1.2.83 on JDK 8 and JDK 17.
- JDK 21 retained-JAR variant is externally reported (FearsOff) and not reproduced here.
- A DNS/Collaborator callback from the active probe is prerequisite evidence only, not proof of code execution.
- The fastjson2 bypass is an independent Chaitin disclosure, not an original finding of this repository.
Organisations named here
- Chaitin
- FearsOff
- Kirill Firsov
CVEs named here
- CVE-2022-25845
Technologies named here
- fjdetect.py
- Fastjson
- fjscan_static.py
- fjscan_probe.py
- fjpayload.py
- Fastjson2
- modern-fd/ lab
- Top-level Docker Compose lab
- Spring Boot
- fastjson2/ lab
- JDK
- DmTomHL/fastjson-1.2.83-gadget-rce
- wouijvziqy/Fastjson-JsonType-RCE-PoC
- Burp Collaborator / interactsh
- Java
- Docker
- Burp Suite
Techniques named here
- Fastjson AutoType @JSONType resource probe abuse
- Remote-JAR + /proc/self/fd reopening chain
- Legacy JDK 8 direct remote-class RCE
- Fastjson2 seeAlso/autoType fallthrough
Related in AppSec
Flowise MCP Security Bypass Enables RCE
Inside an Oracle Database SQL Injection Attack | Huntress
OASIS
