À la découverte de la vulnérabilité de pollution de prototype de minimist
Kirill Efimov
26 mars 2020
0 minutes de lectureLe 11 mars 2020, Snyk a publié une vulnérabilité de sécurité de gravité moyenne liée à la pollution de prototype (CVE-2020-7598) qui affecte le package npm minimist. Cette découverte s’inscrit dans le cadre des recherches menées par l’équipe de recherche en sécurité de Snyk, qui avait déjà mis au jour des vulnérabilités similaires dans d’autres bibliothèques JavaScript de premier plan, telles que lodash et jQuery.
Qu’est-ce qu’une vulnérabilité de pollution de prototype ?
Cette vulnérabilité de sécurité, appelée pollution de prototype, permet aux attaquants de remplacer le prototype d’un objet d’application JavaScript. Dans ce cas, des propriétés contrôlées par l’attaquant peuvent être injectées dans des objets, puis provoquer un déni de service en déclenchant des exceptions JavaScript ou modifier le code source de l’application afin de forcer l’exécution du chemin de code injecté par l’attaquant.
Les recherches actuelles de l’équipe Snyk ont également révélé des vulnérabilités de sécurité similaires dans d’autres packages npm, dont certains sont aussi connus que yargs-parser :

L’équipe de recherche en sécurité de Snyk respecte les règles de divulgation responsable et a collaboré avec les responsables de la maintenance de minimist, de yargs-parser et d’autres projets afin de communiquer nos conclusions, de les valider et de les faire vérifier par les responsables concernés, qui ont confirmé et reconnu la surface d’attaque vulnérable.
Nous tenons à remercier les responsables de la maintenance qui ont réagi rapidement et publié des correctifs dans les meilleurs délais, tout en rétroportant les correctifs de sécurité vers les anciennes versions — par exemple, le correctif de sécurité de minimist pour les versions antérieures à 1.0.0 et le correctif de sécurité de yargs-parser pour les versions antérieures à 13.1.2.
Pollution de prototype dans les analyseurs d’arguments CLI
Notez que dans cet article, je ne vais pas aborder les principes de base de la pollution de prototype : de nombreux articles ont déjà été publiés à ce sujet. Nous avons également publié un article détaillé sur notre blog qui présente une bonne introduction aux vulnérabilités liées à la pollution de prototype.
Dans cet article, je vais plutôt :
Expliquer la nature des analyseurs d’arguments de ligne de commande (CLI) et leur utilisation courante dans l’écosystème JavaScript.
Montrer comment les applications qui s’appuient sur ces types d’analyseurs peuvent être vulnérables aux attaques par pollution de prototype, à l’aide d’exemples concrets de packages vulnérables.
Expliquer le raisonnement derrière l’évaluation de la gravité et l’impact global de ces problèmes sur les applications.
C’est une bibliothèque d’analyse d’arguments de ligne de commande, après tout. N’est-ce pas simplement quelqu’un qui s’attaque lui-même ?
minimist et yargs-parser sont des bibliothèques JavaScript conçues pour analyser les arguments des applications Node.js en ligne de commande. Voyons comment une CLI Node.js peut entraîner une élévation de privilèges locale en raison d’une validation incorrecte des entrées (CWE-20), une vulnérabilité courante qui compte des milliers de cas documentés et de CVE.
Dans l’exemple suivant, nous allons créer un utilitaire système qui permet aux utilisateurs sans privilèges root de redémarrer un serveur. Nous utilisons minimist dans un seul but : afficher une aide succincte pour l’option de ligne de commande --help.
Le code suivant présente notre petite CLI Node.js appelée u-reboot :
Pour distribuer cet outil remarquable plus facilement, nous devons le compiler en binaire autonome. Nous pouvons utiliser pkg pour cela :
Enfin, pour qu’il fonctionne, nous devons attribuer les autorisations appropriées au binaire :
4555 correspond aux autorisations de lecture et d’exécution pour tous les utilisateurs, ainsi qu’à l’indicateur setuid. Pour en savoir plus sur setuid , cliquez ici. En bref, cet indicateur permet d’exécuter le binaire avec les autorisations de son propriétaire (l’utilisateur root, dans notre cas).
Nous disposons maintenant d’un outil en ligne de commande, u-reboot, que chaque utilisateur peut lancer pour redémarrer le serveur ou le poste de travail. Mais nous ne voulons pas leur permettre d’effectuer d’autres opérations sur le serveur.
Comment une telle application en ligne de commande peut-elle être détournée ? N’oubliez pas que les utilisateurs disposent de privilèges limités sur le serveur et ne sont pas censés pouvoir exécuter d’autres commandes en tant que root.
Exploiter des applications CLI Node.js
La vulnérabilité de sécurité dans minimist nous permet de polluer le prototype de Object. Soudain, u-reboot devient vulnérable à un cas classique d’élévation de privilèges.
Vous voyez uid=0(root) dans la sortie ? Nous pouvons maintenant exécuter n’importe quelle commande avec les identifiants root en exploitant la vulnérabilité de pollution de prototype dans minimist, utilisé par la CLI u-reboot.
L’attaque est possible parce que child_peorccess.execSync dispose d’un objet options avec une propriété facultative shell. Si shell est vide, execSync utilise /bin/sh, conformément à la documentation. Mais lorsque nous polluons tous les objets avec une propriété shell égale à /tmp/exploit, execSync utilise notre exploit comme shell.
Cela semble être une vulnérabilité locale. Pourquoi dites-vous qu’elle présente un vecteur d’attaque réseau ?
Cela me rappelle la vulnérabilité shellshock, publiée en 2014. Dans le cas de shellshock, le shell Bash peut être amené à exécuter du code arbitraire injecté par le biais de variables d’environnement. Cette vulnérabilité semble entièrement locale (qui d’autre peut contrôler les variables d’environnement ?), mais Bash est très largement utilisé : de nombreux services web s’en servent pour traiter les requêtes, ce qui permet à un attaquant d’exécuter des commandes arbitraires. Je vous recommande de lire cette brève explication si vous ne connaissez pas encore cette vulnérabilité.
Cette vulnérabilité concerne-t-elle uniquement l’élévation de privilèges ? Non. Notre équipe de recherche a étudié différents cas d’utilisation de minimist et de yargs-parser et a découvert plusieurs exemples intéressants. Je ne vais pas examiner chaque cas en détail : ces exemples montrent que les analyseurs d’arguments CLI ne sont pas toujours utilisés comme on pourrait s’y attendre.
Terminal in React — un composant React qui émule un terminal dans un navigateur web. Il utilise minimist pour analyser les arguments CLI des commandes. Vous trouverez d’autres exemples d’émulateurs de terminal.
Les arguments des chatbots ressemblent souvent à des arguments CLI, n’est-ce pas ? Nous avons trouvé de nombreux exemples où des personnes utilisent effectivement des analyseurs d’arguments CLI dans ce but : 1, 2, 3, 4, 5.
apibone — une bibliothèque qui fournit des interfaces pour des services interrogeables. Elle se contente d’abstraire les objets de requête et de réponse de ses fonctions. Elle utilise yargs-parser pour analyser certaines parties des requêtes HTTP.
En cherchant bien dans les dépôts GitHub open source, vous trouverez d’autres exemples d’usages moins évidents.
Ces applications devraient-elles éviter d’utiliser une bibliothèque comme minimist, destinée à l’analyse des arguments CLI, et la détourner pour créer des applications web et réseau ? Peut-être. Mais chez Snyk, nous estimons que les analyseurs sont des éléments de code particulièrement sensibles. Ils se trouvent généralement au début du traitement des données et interagissent directement avec les entrées utilisateur.
De plus, minimist est en réalité une bibliothèque d’analyse d’arguments à usage général : elle n’est pas directement liée à un élément comme process.argv de Node.js. Vous pouvez plutôt utiliser minimist avec un tableau de chaînes, qu’elle analysera comme s’il s’agissait d’arguments CLI.
Réfléchissez-y : combien de problèmes les analyseurs XML ont-ils causés ? Et les mécanismes de désérialisation de Java ? Vous vous souvenez probablement de l’analyseur JSON bourne, écrit par Eran Hammer après avoir été confronté à des problèmes de pollution de prototype liés à hapi et joi. L’analyseur JSON Bourne a été conçu dans un seul but : se protéger contre les propriétés __proto__ dans une charge utile JSON. Pour en savoir plus, consultez son article.
Comment évaluer la gravité de cette vulnérabilité ?
Pour décrire la vulnérabilité, nous lui avons attribué le vecteur CVSS suivant : CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L.
Vecteur d’attaque — Réseau. Nous avons trouvé minimist et yargs-parser utilisés dans plusieurs chatbots et applications web. Même si l’utilisation de ces bibliothèques dans ces cas n’est pas une bonne pratique, nous ne pouvons pas ignorer le fait que des personnes les utilisent effectivement ainsi.
Complexité de l’attaque — Élevée. Les vulnérabilités de pollution de prototype ne deviennent une réelle menace que si l’attaquant trouve un gadget adapté pour exécuter du code à distance ou effectuer une autre action nécessaire à la poursuite de l’attaque. Dans notre exemple, l’appel « execSync » joue le rôle d’un tel gadget.
Privilèges requis — Aucun. L’attaquant doit pouvoir envoyer une chaîne interprétée comme des arguments CLI. Aucun privilège particulier n’est nécessaire.
Interaction de l’utilisateur — Aucune.
Portée — Inchangée. À mon avis, ces deux propriétés n’ont pas besoin d’explications supplémentaires.
Confidentialité — Faible.
Intégrité — Faible.
Disponibilité — Faible. Ces trois propriétés sont faibles pour les raisons décrites au point 2 : les vulnérabilités de pollution de prototype doivent être évaluées dans le contexte d’une application.
Cette vulnérabilité n’est certainement pas de gravité élevée (son score CVSS est de 5,6, soit une gravité moyenne), mais notre équipe de recherche a clairement identifié de nombreux scénarios d’attaque. Nous estimons que la popularité des deux bibliothèques mentionnées ici justifie une divulgation responsable et un correctif.
Que dois-je faire ensuite ?
Si vous utilisez déjà Snyk pour surveiller vos applications et que vous l’avez connecté à vos dépôts GitHub ou Bitbucket, vous devriez déjà avoir reçu une pull request automatisée de Snyk vous invitant à mettre à niveau vos projets vers les versions corrigées des bibliothèques vulnérables.
Si vous n’utilisez pas Snyk, vous pouvez ajouter vos projets — Snyk est gratuit pour les projets open source — et les importer depuis vos dépôts de code dans le tableau de bord Snyk.
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.
