Skip to main content

Explorer les extensions des attaques par confusion de dépendances via l’aliasage des packages npm

Écrit par
Headshot of Nishant Jain

Nishant Jain

Snyk Advisor for malicious npm package

4 novembre 2021

0 minutes de lecture

Les attaques par confusion de dépendances sont une forme d’attaque visant la sécurité de la chaîne logistique des logiciels open source. Elles exploitent la façon dont les gestionnaires de packages installent les dépendances. Dans un article précédent, nous avons étudié comment détecter et prévenir les attaques par confusion de dépendances sur npm afin de préserver la sécurité de la chaîne logistique.

Dans cet article, nous présentons une extension du problème de confusion de dépendances qui exploite les fonctionnalités d’aliasage des packages de npm. Cette fonctionnalité, proposée et documentée dans l’interface de ligne de commande npm, permet à un utilisateur d’installer un package sous un autre alias. Selon la documentation officielle de npm, prenons l’exemple suivant :

npm install my-react@npm:react

Cela crée l’entrée suivante dans package.json :

dependencies: {
  “my-react”: “npm:react”
}

Les conséquences de l’aliasage des packages npm apparaissent dans la façon dont les autres outils liés aux packages traitent les manifestes, et concernent même le registre officiel npmjs.org. Bien que ce scénario d’attaque n’ait pas de conséquences directes sur la sécurité (car le package aliasé télécharge toujours la version spécifiée dans la commande npm), nous pensons qu’il ouvre la voie à d’autres vecteurs d’attaque.

Mettre en œuvre un scénario d’attaque par aliasage de package npm

Reproduisons l’impact des attaques par aliasage de packages npm pour montrer comment elles peuvent entraîner une confusion de dépendances et l’installation de packages malveillants.

Nous commençons par créer un package nommé deneuve-package-parent qui installe deux versions différentes du package deneuve-package-test : les versions 1.0.0 et 1.2.0. La version 1.0.0 est installée sous le nom d’un package fictif, deneuve-package-private, grâce à l’aliasage des packages npm.

Sur npmjs.com, ce package est répertorié parmi les dépendances de deneuve-package-parent.

Voici le fichier package.json complet, qui illustre l’arborescence des dépendances décrite ci-dessus :

{
  "name": "deneuve-package-parent",
  "version": "1.2.0-beta",
  "description": "This is the parent package!",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Hello\""
  },
  "author": "deneuve@wearehackerone.com",
  "license": "ISC",
  "dependencies": {
    "deneuve-package-test": "^1.2.0",
    "deneuve-package-private": "npm:deneuve-package-test@1.0.0"
  }
}

Nous avons ensuite publié le package sur npmjs, puis consulté la liste de ses dépendances.

Comme vous pouvez le constater, la liste des dépendances du registre npmjs affiche en fait l’alias fictif deneuve-package-private parmi les noms de dépendances :

Page du package npm deneuve-package-parent affichant les dépendances deneuve-package-test et deneuve-package-private

La capture d’écran ci-dessus montre une dépendance nommée deneuve-package-private, que nous avons créée comme alias dans notre fichier package.json, et non comme dépendance réelle. Cet alias (utilisé comme nom de package) n’existe pas réellement dans le registre npmjs — à moins que quelqu’un ne le publie ! C’est là que les risques pour la sécurité de la chaîne logistique entrent en jeu.

Capture d’écran d’une page npm montrant un package privé introuvable, un message 404 et un wombat dessiné.

La question se pose alors : que se passerait-il si quelqu’un repérait ces packages aliasés, puis les publiait sur npm en tant que packages malveillants ? Des utilisateurs désorientés pourraient voir une dépendance répertoriée sur la page officielle d’un package npmjs, puis l’installer simplement en exécutant localement npm install sur leur machine de développement :

$ npm install deneuve-package-private

Ce scénario peut se produire si un développeur décide de déboguer l’application et de télécharger chaque bibliothèque séparément. Soyons honnêtes : à quelle fréquence les développeurs vérifient-ils qu’ils ne téléchargent pas un package censé rester privé ? Une simple erreur ou omission suffit, même lorsque les entreprises ont mis en place des règles contre le téléchargement de packages sans portée.

Nous avons publié sur le registre npmjs un package vide portant ce nom. Comme vous pouvez le voir en consultant l’onglet Dependents, il renvoie au package d’origine, qui le mentionne comme alias parmi ses dépendances :

Page du package npm « dene uve-package-private » indiquant un dépendant, « dene uve-package-parent », et les détails du package

Les outils de développement qui gèrent les noms de packages, comme le registre npmjs lui-même, doivent en tirer la leçon et veiller à ne pas induire leurs utilisateurs en erreur quant aux noms des packages.

Le fait que le typosquattage de noms de packages demeure un vecteur d’attaque efficace contre la chaîne logistique montre que la moindre apparence de légitimité (comme celle que confère l’aliasage des packages) peut considérablement augmenter les chances de réussite d’une attaque.

Contexte de cette découverte

Cette forme d’attaque contre la chaîne logistique a été découverte récemment par moi-même et mon collègue chercheur en sécurité Mario Stathako. Nous l’avons signalée à GitHub et à npm. Je suis étudiant en master et je consacre du temps à la recherche et au développement de ressources de sécurité pour les programmes de bug bounty. Je suis également Snyk Ambassador ! Mario est testeur d’intrusion et participe régulièrement à des compétitions Capture the Flag (CTF) et à des programmes de bug bounty.

La confusion de dépendances a retenu mon attention, car le problème était très simple, mais avait un impact considérable ! Mario et moi avons donc commencé à rechercher cette vulnérabilité dans les programmes privés de HackerOne. Nous voulions voir avec quelle efficacité les entreprises réagissaient aux recherches populaires — et atténuaient les risques associés — après un certain délai. En préparant des packages de preuve de concept pour ces attaques, nous avons remarqué un comportement étrange sur le site NPM : la façon dont le fichier package.json était traité pour différents packages, ainsi que la façon dont leurs dépendances et leurs dépendants étaient répertoriés.

Protégez-vous contre les risques liés à la sécurité de la chaîne logistique

Snyk a développé et publié un outil open source en ligne de commande appelé snync pour vous aider à détecter les attaques potentielles par confusion de dépendances et attaques similaires, et à recevoir des alertes à leur sujet. Découvrez cet outil dans notre article de blog sur la détection et la prévention de la confusion de dépendances sur npm.

Par ailleurs, Snyk Advisor est un outil pratique pour repérer les problèmes de sécurité des packages et de leurs différentes versions. Il indique clairement si un package a été identifié comme malveillant :

Page Snyk Advisor du package npm lyft-dataset-sdk, signalé comme package malveillant utilisé dans une attaque par confusion de dépendances.

Pour finir, voici quelques lectures recommandées sur les bonnes pratiques de sécurité de la chaîne logistique des logiciels open source :

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis de capture du drapeau en regardant à la demande notre atelier virtuel d’initiation.