Cette histoire commence lorsque Sébastien Lorber, responsable de Docusaurus, le projet de documentation open source basé sur React, remarque une modification de Pull Request dans le manifeste du package. Voici le changement proposé au package cliui npm populaire :
Plus précisément, attirant notre attention sur le changement de dépendances npm qui utilisent une syntaxe inconnue :
"dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
La plupart des développeurs s'attendraient à voir une plage de versions semver dans la valeur d'un package ou peut-être une URL Git ou basée sur un fichier. Cependant, dans ce cas, il existe une syntaxe spéciale npm: prefix. Qu'est-ce que ça veut dire?
Qu'est-ce que l'alias de package npm ?
Le gestionnaire de packages npm prend en charge une fonctionnalité d'alias de package qui permet la définition de règles de résolution personnalisées pour les packages. En tant que tel, partout où le package est référencé, via le code ou le fichier de verrouillage, il sera résolu avec le nom et la version spécifiés par l'alias.
Ainsi, dans le cas du changement proposé dans cette demande d'extraction, le package string-width-cjs sera résolu en package string-width dans les versions ^4.2.0. Cela signifie qu'il y aura une entrée de répertoire node_modules pour string-width-cjs mais avec le contenu de string-width@^4.2.0 et un comportement similaire dans le fichier de verrouillage (package-lock.json).
L'alias de package est une fonctionnalité du gestionnaire de packages NPM qui peut être utilisée dans des cas tels que la prise en charge d'ESM vs CJS.
Cela dit, l'alias de package peut être abusé. Dans un article et une divulgation de sécurité remontant à 2021, Nishant Jain, un ambassadeur de Snyk, a démontré comment le registre officiel npmjs pouvait être trompé en désinformant les informations de dépendance basées sur l'alias de package dans le cadre d'une confusion de dépendances et d'un problème de sécurité de la chaîne d'approvisionnement.
La pull request était bénigne et il n'y avait aucun risque d'attaque de la chaîne d'approvisionnement. Cependant, l'inquiétude de Sébastien concernant le nom du package a conduit à la découverte d'un risque de sécurité potentiel.
Pour examiner la pull request, Sébastien a utilisé lockfile-lint. Cet outil vérifie les fichiers de verrouillage tels que package-lock.json ou Yarn.lock à la recherche de signes de falsification, garantissant ainsi qu'aucun package malveillant n'a été injecté à la place du package npm d'origine.
L'exécution de l'outil a affiché les avertissements suivants :
npx lockfile-lint --path package-lock.json --allowed-hosts yarn npm --validate-https --validate-package-names detected resolved URL for package with a different name: string-width-cjs expected: string-width-cjs actual: string-width detected resolved URL for package with a different name: strip-ansi-cjs expected: strip-ansi-cjs actual: strip-ansi detected resolved URL for package with a different name: wrap-ansi-cjs expected: wrap-ansi-cjs actual: wrap-ansi ✖ Error: security issues detected!
Avertissement : lockfile-lint est un outil que j'ai développé en 2019 suite à ma publication qui révélait le problème de sécurité lié aux fichiers de verrouillage : pourquoi les fichiers de verrouillage npm peuvent être un angle mort de sécurité pour l'injection de modules malveillants.
Compte tenu des résultats lockfile-lint ci-dessus, Sébastien a recherché ces noms de packages sur npm et a découvert de manière surprenante qu'ils existent dans le registre public npm :
Sébastien a observé que ces noms de packages existent non seulement sur npm, mais présentent également des caractéristiques suspectes. Les packages n'étaient pas liés à un référentiel de code source public, étaient vides de tout code réel lors de leur inspection et ont été publiés de manière anonyme sans aucune information personnelle associée.
En regardant le package npm strip-ansi-cjs, il n'y a pas de README ni de dépôt de code source. Il existe cependant de nombreux packages légitimes et populaires citant le même comportement.
En fait, ce package particulier est populaire, comme le montrent ses 529 dépendants (autres packages qui dépendent de celui-ci) et 7 274 téléchargements hebdomadaires.
En regardant le code de strip-ansi-cjs, il montre qu'il n'y a qu'un seul fichier dans ce package, le fichier manifeste du package package.json.
Alors, pourquoi un package qui ne fait rien obtient-il autant de téléchargements, et pourquoi tant d'autres packages en dépendent ?
Inspectons l'auteur de ces packages npm.
Les trois packages appartiennent à himanshutester002, et leurs packages ont tous été publiés l'année dernière avec des numéros de version programmatiques. Quelques observations intéressantes à souligner :
Vous pouvez également noter que l'utilisateur himanshutester002 ne dispose d'aucune information identifiable sur cette page de profil utilisateur sur npmjs.
Nous avons précédemment noté que le package strip-ansi-cjs npm compte plus de 500 autres packages qui l'utilisent, ce qui constitue donc potentiellement un indicateur positif de popularité. Regardons-les :
Cela peut sembler crédible en raison de son inscription sur la liste, mais l’est-il vraiment ?
Par exemple, des noms comme clazz-transformer ou réagir-native-multiply ou peut-être gh-monoproject-cli semblent légitimes, mais le sont-ils ?
Voici la page du package npm react-native-multiply :
Ce package n'a pratiquement aucun téléchargement et son auteur est un utilisateur npm anonyme sans aucune information identifiable. Le référentiel d'URL source vers lequel ce package redirige est le https://github[.]com/hasandader/react-native-multiply inexistant. Le profil utilisateur GitHub semble également très suspect et manque d'activité pratique.
Bien que le package npm semble contenir du code source, un examen plus approfondi révèle qu'il s'agit d'un exemple de code généré pour un prototype d'application « hello world ».
Vous devez également vous demander si ce package n'est qu'une bibliothèque de multiplication, alors pourquoi a-t-il besoin de 776 dépendances pour effectuer les opérations suivantes :
import { multiply } from 'react-native-multiply'; const result = await multiply(3, 7);
Alors que certains plaisantent sur la contribution de JavaScript à un arbre astronomique de packages imbriqués grâce à une utilisation excessive des dépendances, un projet avec 776 dépendances directes est déraisonnablement volumineux.
Parmi toutes ces dépendances, se trouvent les 3 packages npm suspects avec lesquels notre histoire a commencé : string-width-cjs, strip-ansi-cjs et wrap-ansi-cjs :
Nous avons mentionné que l'une des dépendances strip-ansi-cjs s'appelait clazz-transformer. Regardons ça :
Expliquons ce qui se passe ici. Le package npm clazz-transformer est intentionnellement mal nommé avec le titre class-transformer sur sa page README. De plus, son référentiel de code source, https://github[.]com/typestack/class-transformer, ne correspond pas au nom du package, ce qui soulève des inquiétudes quant à sa légitimité.
Le typstack/class-transformer du référentiel associé sur GitHub contient le fichier package.json comme suit :
Le fichier package.json sur GitHub ne montre aucune déclaration de dépendances, mais si nous inspectons le code source du package réel sur npmjs, nous voyons les 437 dépendances avec lesquelles ce transformateur clazz est empaqueté. Encore une fois, ils regroupent très commodément les 3 packages *-cjs suspects :
Avant de tirer d'autres conclusions, il est important de mentionner quelques-unes des caractéristiques des packages npm que nous avons observés ci-dessus :
Nos pairs de Sonatype ont déjà identifié des cas similaires d'inondation de registres open source avec des packages. Dans ces cas, l'objectif ultime était que les développeurs se récompensent avec des jetons Tea, qui est une plate-forme Web3 permettant de monétiser des logiciels open source.
La recherche de fichiers tea.yaml dans les packages mentionnés confirme en outre la thèse selon laquelle une partie du but de cette campagne est d'exploiter des jetons Tea grâce à une utilisation abusive de Tea.
Plus tôt cette année, le 14 avril 2024, un utilisateur du forum Tea a publié un commentaire qui conforte davantage les préoccupations concernant l'abus de thé :
Avant de formuler des réflexions finales, je voudrais sincèrement remercier Sébastien Lorber pour son état d'esprit prudent en tant que responsable et pour avoir aidé à dévoiler ces fils de discussion sur une potentielle attaque de chaîne d'approvisionnement npm.
À ce stade, je suis convaincu que je peux continuer à percer des trous dans le reste des packages qui sont censés dépendre de string-width-cjs pour trouver des indicateurs très douteux de légitimité authentique.
Je suppose que tous ces packages dépendants et ces augmentations de téléchargement ont pour seul objectif de créer une fausse légitimité pour les packages 3 *-cjs afin qu'en temps voulu, avec la bonne victime en jeu, ces faux packages seront être installé puis suivre avec une nouvelle version malveillante.
Pour vous aider à rester en sécurité lorsque vous travaillez avec des logiciels open source, je vous recommande fortement d'adopter des pratiques de sécurité et en particulier ces ressources pédagogiques de suivi :
Avons-nous détecté une campagne de sécurité de la chaîne d'approvisionnement au milieu de leurs actes déloyaux, ou s'agit-il uniquement de piste d'argent et, en tant que tel, peut être attribué au spam et à l'abus de registres publics comme npm et GitHub pour extraire des jetons de thé ?
Quelle que soit l'évolution des choses, restez vigilant.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3