Les risques de sécurité d’un sandbox JavaScript utilisant le module VM de Node.js
22 février 2023
0 minutes de lectureVous devez créer un produit qui nécessite d’exécuter du code JavaScript dynamique fourni par les utilisateurs ? Vous pensez peut-être que le module VM de Node.js est une solution viable pour créer un sandbox JavaScript. Dans cet article, nous verrons pourquoi cette approche est loin d’être recommandée et quelles en sont les implications en matière de sécurité.
De temps à autre, un projet vient bousculer les tâches rudimentaires et routinières du développement backend. Des API ? Des files de messages ? Des traitements lourds et des besoins importants en calcul ? Non. Voici une tâche du backlog à prendre en considération :
Cet exemple est un peu vague, car il s’agit d’un cas d’usage générique portant sur l’exécution de code non fiable fourni par des utilisateurs. Il existe toutefois des exemples concrets où cela peut s’avérer nécessaire, notamment :
Le produit replit vous permet de coder dans le cloud et d’exécuter du code dans un IDE personnalisé.
Diverses plateformes d’entraînement au code et d’entretien technique, comme « leet code », vous permettent d’écrire du code personnalisé, par exemple pour implémenter un algorithme donné ou rédiger des tests.
Voici le module VM de Node.js.
Le module VM de Node.js
Le module central node:vm permet aux développeurs de compiler et d’exécuter du code fourni dynamiquement dans des contextes de machine virtuelle V8. Cela peut d’abord vous faire penser à la fonction JavaScript eval, qui présente un risque de sécurité bien connu. Mais le module VM de Node.js est-il plus sûr ? Après tout, il s’agit d’une « machine virtuelle ».
Voyons un exemple concret :
Dans l’extrait de code ci-dessus, le code JavaScript personnalisé fourni par l’utilisateur (indiqué par la variable userInputCustomJavaScriptCode) est exécuté spécifiquement dans un contexte donné de variables, à l’aide de vm.runInContext(). Cet extrait s’exécute correctement et produit les résultats suivants :
Les attaquants peuvent toutefois chercher à exploiter ce type de code JavaScript dynamique en modifiant d’autres variables que celles définies à l’origine. Dans cet exemple fictif en Node.js, une variable nommée productExpirationDays définit la durée de validité pour l’utilisateur. Que se passerait-il si un attaquant modifiait son code JavaScript dynamique pour augmenter cette valeur ?
Si nous remplacions l’exemple précédent de saisie utilisateur par celui-ci, qui tente d’augmenter le nombre de jours de validité, nous obtiendrions l’erreur suivante :
Cette erreur s’explique par le fait que la variable productExpirationDays n’est pas définie ni présente dans la portée du contexte de la machine virtuelle où le code JavaScript dynamique est exécuté.
En somme, il semble que nous ayons trouvé un moyen d’exécuter du code JavaScript dynamique de façon sécurisée dans un sandbox JavaScript isolé.
Un sandbox JavaScript non sécurisé
L’exemple de code utilisant createContext() et vm.runInContext() du module VM de Node.js était trop simpliste. Malheureusement, dans la réalité, les entrées malveillantes des utilisateurs recourent souvent à des méthodes plus astucieuses, créatives et efficaces pour s’échapper du sandbox JavaScript.
Voyons comment un attaquant peut fournir du code non sécurisé entraînant une attaque par déni de service contre une application en cours d’exécution. Prenons le script Node.js suivant :
Dans l’exemple de code ci-dessus, l’utilisateur a ajouté une boucle infinie, while(true) {}, à sa saisie. Même si ce code ne modifie aucune autre variable de l’application, il provoque une attaque par déni de service.
Les risques liés à un sandbox JavaScript non sécurisé concernent également l’exécution de code à distance. Avec this.constructor.constructor, nous pouvons accéder à l’objet JavaScript Function. Une fonction JavaScript peut accepter du code sous forme de chaîne, puis l’exécuter. Notre attaque exploite cette caractéristique et, à l’aide d’une fonction immédiatement invoquée (IIFE), affiche les variables d’environnement du processus Node.js en cours d’exécution :
L’exécution de l’extrait de code ci-dessus affiche le résultat de process.env, qui répertorie toutes les variables d’environnement.
Vous devriez désormais mesurer l’impact d’une exécution de code à distance lorsqu’elle permet d’exécuter du code non fiable dans le module VM de Node.js. Si les utilisateurs peuvent exécuter du code personnalisé, ils ont un accès complet à l’environnement d’exécution du serveur Node.js et peuvent lancer des processus, accéder au système de fichiers et bien plus encore.
En résumé
Dans un environnement Node.js, un sandbox JavaScript non sécurisé peut avoir de graves conséquences et paralyser toute une application. Nous avons vu comment un attaquant peut exploiter le sandbox JavaScript et fournir des entrées malveillantes qui dégradent une application Node.js, provoquant ainsi une vulnérabilité de déni de service. Mais la surface d’attaque ne s’arrête pas là. Nous avons également vu qu’une exécution de code à distance est possible, permettant aux attaquants d’exécuter du code personnalisé dans des environnements serveur Node.js et de mettre en péril toute la plateforme applicative.
En réalité, la faille de sécurité créée par un sandbox JavaScript utilisant le module VM de Node.js n’est que le début d’une violation de données plus vaste. Dès qu’un seul serveur d’application Node.js est compromis, des informations sensibles peuvent être révélées, comme les secrets d’accès à une base de données ou à des services cloud. Un attaquant peut alors poursuivre son exploitation et se déplacer latéralement au sein du réseau déployé.
La bonne pratique consiste donc à ne pas s’appuyer sur le module VM de Node.js comme sandbox sécurisé pour exécuter du code JavaScript non fiable. La documentation de l’API Node.js le précise clairement : « Le module node:vm n’est pas un mécanisme de sécurité. Ne l’utilisez pas pour exécuter du code non fiable. »
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.
