Diffusion massive de paquets malveillants sur NPM, téléchargés plus de 86 000 fois
(arstechnica.com)- Il a été confirmé que plus de 100 paquets malveillants destinés au vol d’identifiants ont été publiés sur le dépôt NPM sans être détectés depuis août, et qu’ils ont été téléchargés au total plus de 86 000 fois
- La société de sécurité Koi rapporte qu’une campagne d’attaque baptisée PhantomRaven a distribué 126 paquets malveillants en abusant de la fonctionnalité Remote Dynamic Dependencies (RDD) de NPM
- Le RDD est un mécanisme qui permet à un paquet de télécharger dynamiquement du code de dépendance depuis des domaines non fiables, ce qui empêche sa détection par les outils d’analyse statique
- Les attaquants ont exploité cette fonctionnalité pour télécharger du code malveillant via des connexions HTTP, tandis que les métadonnées des paquets affichaient « 0 Dependencies », empêchant les développeurs et les scanners de sécurité de s’en apercevoir
- Cette faiblesse structurelle met en évidence les limites de la gestion de la sécurité dans l’écosystème NPM ainsi que les risques des mécanismes d’installation automatique
Propagation de paquets malveillants dans le dépôt NPM
- Des attaquants ont exploité une faiblesse structurelle du dépôt de code NPM pour publier, depuis août, plus de 100 paquets destinés au vol d’identifiants
- La plupart de ces paquets ont été diffusés sans être détectés, avec un total cumulé de plus de 86 000 téléchargements
- La société de sécurité Koi a nommé cette attaque la campagne PhantomRaven et a analysé l’exploitation d’une fonctionnalité spécifique de NPM
- Selon Koi, sur les 126 paquets malveillants, environ 80 étaient encore présents sur NPM au moment de la rédaction de l’article
Structure vulnérable de Remote Dynamic Dependencies (RDD)
- Le RDD est une fonctionnalité qui permet à un paquet de télécharger dynamiquement du code de dépendance depuis des sites externes
- En temps normal, les dépendances sont récupérées depuis l’infrastructure de confiance de NPM, mais le RDD autorise aussi des téléchargements via des connexions non chiffrées comme HTTP
- Les attaquants de PhantomRaven ont utilisé cette fonctionnalité pour configurer le téléchargement de code depuis des URL malveillantes (ex. :
http://packages.storeartifact.com/npm/unused-imports)- Ces dépendances sont invisibles pour les développeurs comme pour les scanners de sécurité, et les informations du paquet affichent « 0 Dependencies »
- En raison du mécanisme d’installation automatique de NPM, ce code de dépendance « invisible » est exécuté automatiquement
Limites de détection des outils de sécurité
- Oren Yomtov de Koi a déclaré que « PhantomRaven est un cas qui exploite avec sophistication les angles morts des outils de sécurité existants »
- Le RDD n’est pas détecté par les outils d’analyse statique
- Cela a permis aux attaquants de contourner les vérifications de sécurité et de distribuer du code malveillant
Facteurs de vulnérabilité supplémentaires
- Koi explique que les dépendances téléchargées via le RDD sont retéléchargées depuis le serveur des attaquants à chaque installation
- En l’absence de cache ou de gestion de versions, il existe une possibilité que du code malveillant différent soit injecté selon le moment de l’installation, même pour un même paquet
- Cette structure de téléchargement dynamique complique la vérification de l’intégrité des paquets
Structure et contexte de NPM
- NPM est un gestionnaire de paquets pour JavaScript, maintenu par npm, Inc., une filiale de GitHub
- Il s’agit du gestionnaire de paquets par défaut de Node.js et il se compose d’un client en ligne de commande et du npm registry
- Le registry stocke des paquets publics ainsi que des paquets privés payants, consultables via le site web
- Cet incident est présenté comme un exemple montrant que la structure de gestion automatique des dépendances de NPM peut être détournée à des fins d’attaque
Autres mentions
- En fin d’article, il est mentionné qu’il faudrait bloquer l’exécution inutile de JavaScript
- Toutefois, cette attaque est soulignée comme un cas où même du code JavaScript indispensable a été détourné
2 commentaires
J’ai créé un script de scanner en temps réel.
Depuis le chemin du dépôt suspect,
npx sha1-hulud-scanneril suffit de le saisir.
Code source : https://github.com/developerjhp/sha1-hulud-scanner
Avis Hacker News
En ce moment, j’ai configuré un alias pour exécuter la commande
npmdans un conteneur DockerComme ça, mes variables d’environnement ne sont pas exposées, il n’a pas accès aux fichiers hors du répertoire courant, ni aux fichiers de configuration comme
.bashrcRéférence : Run tools inside Docker
npmtélécharge du code arbitraire qui sera exécuté immédiatementÀ la place, je recommande
pnpm. Par défaut, il n’exécute pas les scripts de cycle de vie et permet de mettre en liste blanche ceux à autoriserSi on veut une vraie protection, il faut sandboxer non seulement l’installation mais aussi toute l’exécution
Bloquer uniquement les post-install, comme on le fait maintenant, n’est qu’une demi-mesure. Les attaques sur la chaîne d’approvisionnement deviennent de plus en plus dangereuses
Si
neovimouvscodeest compromis, il peut déjà faire des choses très dangereuses avec les droits de l’utilisateurUn simple alias marche pour
node/npm, mais il est difficile à appliquer à d’autres programmes, puisqu’il faut monter dans le conteneur les ressources nécessairesJe me le demandais depuis longtemps : pourquoi les gens exécutent
npmsur leur système comme si de rien n’était ?Quand on est habitué aux builds reproductibles avec
make, c’est choquant de voirnpmtélécharger quelque chose de différent à chaque fois et produire des résultats différentsJe trouvais déjà étrange de lier même la génération du CSS à des dépendances npm. J’ai donc essayé de figer tout l’environnement npm dans Docker, mais ça semble être un combat perdu d’avance
maven,nuget,pip,npm, c’est pareilSi on dépendait encore des gestionnaires de paquets des distributions comme avant, l’écosystème rapide qu’on a aujourd’hui serait impossible
Cela dit, de nouveaux gestionnaires de paquets plus sécurisés apparaissent. Critiquer l’outil sans comprendre la raison de son existence n’est pas juste
npmdans Docker, j’aimerais savoir si tu validais cet environnement après chaque mise à jour des dépendancesEn réalité,
npmetpnpmfigent déjà les dépendances par défaut avec des fichiers locknpm install thing”Beaucoup d’open source se retrouve rempli de code écrit pour le CV plutôt que pour la qualité, et finit par servir à fabriquer des traqueurs publicitaires de géants du web ou des applis de portefeuille
npm installne se contente pas de télécharger un paquet, il exécute du codeLes hooks preinstall, install et postinstall de
package.jsonsont réellement exécutésQuelle raison légitime peut justifier l’exécution de commandes arbitraires pendant l’installation ?
Rapport lié : PhantomRaven npm malware
Autre cas : blog Socket.dev
Par exemple, les paquets du noyau Linux exécutent des scripts post-install pour régénérer l’initramfs, mettre à jour GRUB, etc.
La plupart des paquets DEB/RPM contiennent ce type de scripts. C’est donc un problème de conception en soi
npmpermet à n’importe qui de publier un paquetLes distributions Linux ont un système de mainteneurs de confiance et peuvent même établir directement une racine de confiance basée sur PGP
En revanche,
npm,pip,rubygems,cargo, etc. ne sont au fond qu’une version sophistiquée de “curl | bash”Ce type de build post-install était nécessaire pour réduire la charge de maintenance
Package.swiftMais j’ai entendu dire qu’il est fortement sandboxé, ce qui rend l’abus difficile
Référence : documentation SwiftPM, PackageDescription
pnpm v10désactive désormais tous les scripts de cycle de vie par défaut, et demande une autorisation explicite de l’utilisateurDiscussion liée
Quand on voit les attaques récentes contre
npm, on se demande si développer avecnpmest encore sûrÀ chaque fois que je démarre un projet React, des centaines de paquets s’installent, sans que je sache vraiment ce qu’ils font
Côté back-end, on installe explicitement uniquement les paquets nécessaires, mais le front-end ressemble à une boîte de Pandore de vulnérabilités
npmest le plus gros et fait plus souvent les gros titresjjen Rust : 470 paquets.wan2gpen Python : 211 paquets. C’est partout pareilComme dans l’affaire
xz, chaque dépendance repose sur des individus pris au hasard, et il faut croire qu’ils ne se feront pas piéger par de l’ingénierie socialePyPIn’est pas sûr non plus. Il y a déjà eu des cas où du code malveillant a été injecté dans des paquets légitimes via le piratage de GitHub ActionsChaque fois que je développe avec des frameworks comme Angular ou Vue, ça m’inquiète
Quand je vois les milliers de dépendances dans
node_modules, j’ai l’impression d’un désastre annoncéIl suffit qu’un développeur open source se fasse piéger par phishing pour que tout soit compromis
L’écosystème JavaScript est fondamentalement cassé. Une simple faute de frappe peut exposer à une attaque sur la chaîne d’approvisionnement
C’est aussi possible avec NuGet ou Maven, mais là-bas il y a une bibliothèque standard plus riche, donc moins de dépendances et davantage de contrôle
Ce n’est pas parfait, mais c’est déjà un cran au-dessus
Sur les 86 000 téléchargements, il est probable que la plupart ne viennent pas de vrais utilisateurs mais de scanners automatisés ou de bots
Quand on publie une nouvelle version, on voit parfois des centaines de téléchargements en un ou deux jours, sans qu’il s’agisse forcément d’humains
Autrement dit, il se peut qu’il n’y ait presque aucun utilisateur réellement infecté
Il y a aussi beaucoup d’attaques visant des noms de paquets hallucinés par des chatbots IA. Ce n’est pas qu’une simple statistique
Pour une explication plus détaillée de l’attaque, voir l’article de BleepingComputer
Je me demande s’il existe un moyen de détecter ou filtrer, pendant
npm install, les paquets qui utilisent des URL HTTP comme dépendancesComme ils peuvent envoyer une charge utile différente selon le demandeur, les scanners classiques ont du mal à les détecter
En tant que développeur amateur, je me demande comment me préparer à ce type d’attaques de la chaîne d’approvisionnement
Quand on suit des tutoriels connus et qu’on installe des dépendances, on finit facilement par baisser la garde sur la sécurité
Je fais aussi tourner plusieurs services dans mon homelab, et je crains qu’un bot ne s’y infiltre. Par où commencer ?
Ce n’est pas une garantie parfaite, mais c’est bien mieux que de laisser tout le serveur se faire compromettre
Copier directement uniquement le code nécessaire est aussi une bonne manière d’apprendre et une approche plus sûre
Avec ce type de structure, on peut établir la confiance au niveau de la distribution sans que des millions d’utilisateurs aient à tout vérifier eux-mêmes
Exemples : Hono, Zod
Je suis récemment passé à Bun, qui intègre par défaut des éléments comme des pilotes de base de données ou un client S3, ce qui réduit les téléchargements supplémentaires
Une structure où des dépendances sont récupérées dans les hooks de cycle de vie peut devenir à tout moment un point de bascule pour une attaque
Même si tout est sain aujourd’hui, si le propriétaire est piraté plus tard ou change d’avis, cela peut devenir du code malveillant
Au final, ce type de hook d’installation est une conception non viable à long terme