Laboratorios Docker + escáner defensivo para RCE de carga remota de clases en fastjson. fastjson 1.2.66-1.2.83: sonda de recursos @JSONType (CVE-2026-16723). fastjson2 2.0.57: el @type del atacante alcanza loadClass con autoType DESHABILITADO mediante tipos polimórficos (@JSONType(seeAlso) / Jackson @JsonSubTypes). Payloads de solo marcador; controles safeMode + JDK17.
@JSONType de FastjsonEste repositorio conserva ahora dos líneas de investigación distintas de Fastjson:
modern-fd/ es la reconstrucción recomendada, solo con marcador, de la cadena remota JAR/descriptor-de-archivo de Fastjson 1.2.83 en un solo cuerpo, sobre Spring Boot 3, Tomcat embebido normal y JDK 17. Usa el sumidero literal de DTO fijo JSON.parseObject(body, BoundEnvelope.class) con AutoType deshabilitado.scanner/ contiene detección pasiva de peticiones/logs, inventario estático de artefactos y una sonda de alcanzabilidad que no ejecuta código.El fallo:
ParserConfig.checkAutoTypesondea cada valor@typeen busca de la anotación@JSONTypehaciendogetResourceAsStream(typeName.replace('.','/') + ".class"). En combinaciones modernas de Linux/JDK, una sonda remotajar:httppuede dejar el JAR en caché tras un descriptor abierto; luego, las sondasjar:file:/proc/self/fd/Nen el mismo cuerpo pueden reabrirlo con nombres de clase válidos e inicializar una clase anotada. La composición exacta de 1.2.83 funciona con AutoType deshabilitado y a través de un DTO fijo que contieneList<Object>. Por tanto, la vinculación por sí sola no es una mitigación. Explicación completa:docs/MECHANISM.md.
La revisión complementaria de todo el proyecto abarcó 2.041 filas invocables/inicializadores estáticos en los 193 archivos Java de producción de Fastjson 1.2.83. La tabla siguiente prioriza los resultados de mayor impacto; no es una afirmación de que cada despliegue de Fastjson esté afectado. Este repositorio reproduce directamente F105. Las entradas restantes resumen la revisión de código fuente sellada por separado y la evidencia de laboratorio acotada.
| Prioridad | Hallazgo | Resultado probado | Límite importante |
|---|---|---|---|
| 1 | F105 — ejecución remota de bytecode @JSONType | Inicialización de clases suministrada por el atacante a través de cargadores compatibles de Spring Boot, incluyendo la ruta directa de JDK 8 y la continuación /proc/self/fd/N de JAR retenido en Linux/JDK 17 | Requiere un portador @type alcanzable por el parser, un cargador Boot/TCCL compatible, salida de red (egress), SafeMode/IgnoreAutoType desactivados y un JAR exacto del atacante. La ruta moderna de DTO fijo necesita además un carril de valor genérico (el laboratorio usa List<Object>), procfs en Linux, un descriptor retenido y alineación exacta de nombres; no es universal en todos los JDK, cargadores u SO |
| 2 | F1/F45 — ejecución de comandos de TemplatesImpl | Ejecución de comando marcador a través de la API de DTO fijo, incluyendo una propiedad de cuerpo ignorada | Requiere una política de servidor debilitada: admisión de clases, AutoType y población de campos privados o rutas equivalentes; los valores predeterminados sin modificar lo bloquean |
| 3 | F70/C016 — almacenamiento en búfer y expansión GZIP sin límite | Las rutas de byte/InputStream tipado y DTO anotado se expanden o almacenan en búfer sin un límite de salida; se reprodujo OOME de Java con montón limitado | Se requiere alcanzabilidad del endpoint/esquema y de los bytes del atacante; no se estableció una caída en toda la producción |
| 4 | F18/C089 — agotamiento de la pila del hilo del parser | Los valores de objetos ordinarios profundamente anidados pueden producir StackOverflowError con el análisis predeterminado | Impacto en la disponibilidad del hilo de petición; no es un fallo invariable de la JVM ni de todo el servicio |
| 5 | F120/C162 — SSRF HTTP de esquema fijo / carga de recursos locales | JEditorPane/JTextPane.page controlado por el cuerpo realiza peticiones HTTP y puede cargar contenido file: acotado en el estado del Document | Requiere que la aplicación declare el tipo Swing; no se probó exfiltración automática de respuestas ni RCE |
| 6 | F118/C160 — fallo de autorización/integridad de datos por colisión de hash | Una colisión Unicode distinta de FNV-1a-64 puede vincularse a una constante enum privilegiada o dirigir la mutación JSONPath al setter de bean equivocado | Requiere una colisión utilizable y confianza posterior, o una operación de mutación JSONPath expuesta; no hay admisión de clases ni RCE |
| 7 | F121/C163 — alcanzabilidad JNDI de JdbcRowSet fijo | El orden exacto de los setters provocó una conexión JNDI/LDAP saliente seleccionada por el cuerpo | La evidencia se detiene en una conexión: no hay respuesta de naming, object factory, carga de bytecode ni RCE |
| 8 | F2/F45 — resolución DNS predeterminada | La resolución de nombres de host controlada por el atacante funciona con la configuración predeterminada y a través de una propiedad ignorada de DTO fijo | Solo interacción DNS/OOB, no SSRF HTTP genérico ni RCE |
Consulta findings/FINDINGS.md para ver las etiquetas de validación, prerrequisitos, hallazgos de menor nivel, prioridades de remediación y límites negativos explícitos.
Este repositorio es para educación, investigación defensiva y pruebas autorizadas de sistemas que posees o que tienes permiso explícito de probar. La publicación en el host, cuando es compatible con la red interna del laboratorio moderno, se solicita únicamente en 127.0.0.1; sus scripts ejecutan la prueba completamente dentro de esa red aislada. El laboratorio moderno no tiene una primitiva de ejecución de procesos y solo establece un marcador fijo dentro de la JVM. El laboratorio heredado de JDK 8 sí ejecuta id y escribe su salida en /tmp/PWNED; mantenlo aislado. No apuntes el exploit heredado ni la sonda activa a sistemas no autorizados.
El directorio scanner/ incluye cuatro herramientas Python 3 sin dependencias (sin instalaciones pip).
fjdetect.py — inspecciona pasivamente cuerpos de petición JSON decodificados o logs JSON estructurados en busca de semillas de JAR remoto y secuencias /proc/self/fd o /dev/fd.fjscan_static.py — inventaría jars/wars/ears para la combinación vulnerable (contenido verificado por metadatos de 1.2.83 × contenido real de la clase del cargador de Spring Boot). Las versiones 1.2.48–1.2.82 con sonda y los candidatos solo de metadatos/nombre de archivo se informan por separado para revisión. Amigable para puertas de CI (código de salida 2 en EXPOSED).fjscan_probe.py — comprobación activa y segura de alcanzabilidad: dispara el @type contra un canario que tú controlas (listener integrado o Burp Collaborator / interactsh) y correlaciona la devolución de llamada de obtención de recursos. Su listener integrado devuelve un 404 vacío; configura los listeners externos de forma equivalente. Una devolución de llamada no prueba la carga de clases ni RCE.fjpayload.py — genera cuerpos de obtención de recursos remotos para pruebas manuales; usa solo un listener vacío/404 cuando no se pretende ejecutar.# 1) passive request/log inspection
python3 scanner/fjdetect.py --ndjson gateway.jsonl
# 2) inventory build artifacts / unpacked images (parallel)
python3 scanner/fjscan_static.py /path/to/artifacts --threads 16