Skip to content

Back to the catalog

dinosn/fastjson-jsontype-rce-lab
github.comrepo

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.

TL;DR Reconstructed Fastjson and fastjson2 autoType-bypass RCE chains plus Python scanner and probe tooling for detection and safe reachability testing.
Document

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=true blocks 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.sh

Legacy lab (isolated only):

make up
make exploit
make down

Scanning 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.txt

Mitigations 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 @JSONType jar sink (dots become slashes); tools fall back to --probe-type dns against Inet4Address, 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