12 choses étranges qui peuvent arriver après l'installation du paquet npm

Il y a quelques mois, j'ai lancé un projet appelé malveillants-packages (alias "malveillants packages"). Il surveille les mises à jour dans le référentiel npm, télécharge tous les nouveaux modules, puis les vérifie pour les poux - il recherche l'activité réseau, les opérations suspectes avec le système de fichiers, etc. Même les petits projets sur node.js ont souvent une grande arborescence de dépendances, et les développeurs n'ont physiquement aucun moyen de les tester tous. Cela donne aux attaquants une énorme marge de manœuvre, et la question se pose - combien de registre désagréable se cache dans les coins sombres du registre npm? 180 000 colis vérifiés plus tard, j'ai obtenu une réponse approximative.


image


Et cette réponse - peut-être pas tant que ça.
[note: sur support il y a une version anglaise de cet article, également par ma paternité]


Que peut faire un package npm avec votre système?


Le package a deux principaux moyens de vous nuire - lors de l'installation / désinstallation et au moment du lancement de votre application. Examinons les deux options avec des exemples.


Les scripts NPM permettent aux packages d'exécuter des commandes arbitraires au moment de l'installation et de la désinstallation. Il s'agit notamment de la preinstall , de l' install , de la postinstall , de la preuninstall et de la postuninstall , qui sont exécutées automatiquement par npm au moment approprié du cycle de vie du package. Que peuvent-ils faire? Tout est la même chose que votre utilisateur actuel peut faire - par exemple, supprimer toutes vos photos des dernières vacances ou fusionner l'historique de votre navigateur dans le FBI (bien que, très probablement, il l'ait déjà). Ce comportement peut être désactivé en passant l' --ignore-scripts , mais, premièrement, personne ne le fait, et deuxièmement, de cette façon, vous pouvez casser un tas de paquets assez fiables. C'est grâce à des scripts que l' attaque sensationnelle contre ESLint a été menée, ce qui a affecté les utilisateurs d' eslint-scope (6 millions d'installations par semaine) et d' eslint-config-eslint (2 000 installations par semaine).


Le package obtient une deuxième chance de compliquer votre vie lors de l'initialisation (se produit généralement lors du premier appel à require ). Il a maintenant la possibilité de modifier des variables globales et d'autres packages, par exemple, pour voler la clé privée de votre portefeuille bitcoin, ou pour rendre la méthode crypto.randomBytes pas si aléatoire .


image


Combien de packages malveillants ont été détectés?


Eh bien, la liste ne peut pas être qualifiée d'impressionnante, au total, 3 packages ont été trouvés qui ont été supprimés du référentiel npm par les efforts de l' équipe de sécurité npm . Passons en revue:



Malgré les résultats très modestes, en train d'analyser tous les paquets suspects (et j'ai regardé plus de 3000 rapports pour trouver ces trois perles), beaucoup de choses drôles et pas très nombreuses ont été trouvées auxquelles vous ne pensez généralement pas (ou essayez soigneusement de ne pas penser) en tapant npm install . Imaginons donc que vous sélectionniez accidentellement l'un des nombreux packages du référentiel et que vous l'installiez. Qu'est-ce qui pourrait mal tourner?


1. Un package peut remplacer les méthodes des autres packages (y compris celles de la livraison standard de Node.js)


Cependant, si vous lisez quelques paragraphes précédents ou si vous travaillez avec l'écosystème javascript depuis plus d'une semaine, il est peu probable que ce soit une nouvelle pour vous. Mais l'ampleur de cette catastrophe pourrait bien vous échapper. Donc, si votre projet a au moins quelques dépendances, alors probablement la méthode fs.closeSync que vous avez déjà substituée (et peut-être plus d'une fois). Un grand nombre de packages modifient l'API de quelqu'un d'autre, mais seuls quelques-uns ont au moins une bonne raison à cela. Parmi les «champions», on trouve graceful-fs avec 12 millions d'installations par semaine, ce qui redéfinit des dizaines de méthodes à partir de fs . Il convient également de noter async-listener , qui remplace 46 méthodes différentes , y compris le malheureux crypto.randomBytes , qui m'a un peu dérangé lorsque j'ai découvert cela pour la première fois.


Imaginez à quoi cela ressemblerait pour un bogue provoqué par un tel remplacement d'une certaine dépendance dans les profondeurs de la hiérarchie. Cependant, il n'y a aucune raison de s'inquiéter, car ...


2. Le package peut déterminer l'API modifiée pour y apporter des corrections supplémentaires


image


Oui, certains packages le font (le plus souvent en ce qui concerne les mêmes graceful-fs ) en utilisant les merveilles de l'acrobatie comme /graceful-fs/.test(fs.closeSync.toString()) . Donc, si vous rencontrez soudainement des problèmes incompréhensibles dans la bibliothèque standard, essayez simplement d'installer quelques packages npm aléatoires. Ou éteignez simplement l'ordinateur et promenez-vous dans le parc le plus proche, la vie est trop courte pour comprendre tout cela.


3. Il peut envoyer des analyses


Adblock ne vous protégera pas si des choses se produisent dans la console, et les auteurs de certains packages l'utilisent avec succès. Certains envoient les informations les plus élémentaires, comme ecdsa-csr :


 // POST https://api.therootcompany.com/api/therootcompany.com/public/ping { "package":"ecdsa-csr", "version":"1.1.1", "node":"v10.14.2", "arch":"x64", "platform":"linux", "release":"4.9.125-linuxkit", "action":"install", "ppid":"eDSeYr9XUNRi9WhWli5smBNAvdw=" } 

Certains ne sont pas si timides. Ici, par exemple, fait partie du rapport sans serveur (l'original est 2 fois plus grand):


 // POST https://tracking.serverlessteam.com/v1/track { "userId":"0e32cba0-14ef-11e9-9f89-b7ed4ca5dbba", "event":"framework_stat", "properties":{ "version":2, "general":{ "userId":"0e32cba0-14ef-11e9-9f89-b7ed4ca5dbba", "context":"install", "timestamp":1547135257977, "timezone":"GMT+0000", "operatingSystem":"linux", "userAgent":"cli", "serverlessVersion":"1.35.1", "nodeJsVersion":"v10.14.2", "isDockerContainer":true, "isCISystem":false, "ciSystem":null } } } 

Heureusement, jquery n'envoie aucune statistique, vous pouvez donc l'installer secrètement de tout le monde. Pour le moment.


4. Votre ordinateur peut être utilisé à la place d'un serveur CI / CD


Pourquoi voudriez-vous compiler votre package si vos utilisateurs peuvent le faire pendant l'installation ? Vous pouvez obtenir un résultat supplémentaire si vous spécifiez uniquement la version principale du compilateur requis, par exemple typescript@3 . Un espoir pour les gars lettrés de Microsoft qui savent faire le bon semver.


Est-il possible d'aller encore plus loin? Bien sûr !


 "postinstall": "eslint --ext .js,.vue --fix src" 

Maintenant, vous pouvez dormir paisiblement - tous les utilisateurs recevront des sources parfaitement formatées pour votre package.


5. Il peut essayer de vous faire peur.


image


Si vous avez regardé toutes les séries Mr. Robot, mais toujours pas suffisamment motivé pour lire les réseaux informatiques et faire quelque chose de vraiment impressionnant, c'est-à-dire une solution simple - montrez vos compétences au monde entier à travers quelques lignes dans un script de postinstall - postinstall . C'est exactement ce que l'auteur de pizza-pasta a fait (et en même temps m'a présenté KDPV).


 { "name": "pizza-pasta", "author": "Zeavo", "scripts": { "install": "mkdir -p ~/Desktop/hacked && touch ~/Desktop/hacked/pwnddddd && wget https://imgur.com/download/KTDNt5I -P ~/Desktop/hacked/", "postinstall": "find ~/.ssh | xargs cat || true && printf '\n\n\n\n\n\nOH HEY LOOK SSH KEYS\n\n\n\nHappy Birthday! Youve been h4ck0red\n\n\n'" } } 

6. Le package peut charger et exécuter des scripts bash


Avez-vous entendu dire que curl|bash pas une bonne idée ? Sinon, vous pourriez bien être un employé ORESoftware qui a tout un tas de packages avec des lignes similaires dans un script de postinstall - postinstall :


 curl --silent -o- https://raw.githubusercontent.com/oresoftware/realpath/master/assets/install.sh | bash 

Jusqu'à présent, il n'y a rien de criminel dans ce script ... Pour l'instant. J'espère que tous ceux qui ont accès au master en oresoftware/realpath sont des gens extrêmement honnêtes et décents.


7. Un mot de passe peut vous être demandé


L'auteur de magicleap a trouvé une façon plutôt inhabituelle de distribuer un paquet privé via un référentiel public. Son projet consiste en une archive chiffrée et des utilitaires pour le déchiffrer - mais seulement si vous mettez la bonne clé dans la MAGICLEAP environnement MAGICLEAP :


 // : https://github.com/modulesio/magicleap/blob/master/decrypt.js var key = process.env['MAGICLEAP']; console.warn('Decrypting magicleap module with MAGICLEAP environment variable'); const ws = fs.createReadStream(path.join(__dirname, 'lib.zip.enc')) .pipe(crypto.createDecipher('aes-256-cbc', Buffer.from(key, 'base64'))) .pipe(fs.createWriteStream(path.join(__dirname, 'lib.zip'))); 

8. Le paquet peut se patcher pendant l'installation


L'auteur de fake-template n'a pas le temps de séparer les tests du code immédiat, d'autant plus que c'est facile à faire en ajoutant un commentaire spécial à la fin des lignes de test:


 // : https://github.com/framp/fake-template/blob/master/index.js const template = (string, tag=defaultTag) => { if (mode !== 'literal') throw new Error('Invalid template') return (context={}) => tag(literals, ...expressions.map(evalInContext(context))) } assert.equal(template('')(), ``) // TEST assert.equal(template('abc')(), `abc`) // TEST const dog = 'Orlando' // TEST assert.equal(template('abc ${dog} lol ${cat}')({dog}), `abc ${dog} lol ${cat}`) // TEST 

Et puis supprimez-les via sed :


 "postinstall": "sed -i '/\\/\\/ TEST/d' index.js" 

Simple et élégant!


9. Le package peut modifier les paramètres npm


À mon humble avis, package-json.lock est une grande chose qui peut sauver de tout un tas de problèmes causés par la négligence des autres développeurs. Cependant, certains opposants à cette idée ont de très bons arguments contre:


 "preinstall": "npm config set package-lock false" 

10. Il peut changer l'arrière-plan de votre bureau sur une photo de Nicolas Cage


image


Voici un lien, juste au cas où - https://www.npmjs.com/package/cage-js . Peut-être valait-il la peine d'enregistrer ce package comme malveillant.


11. Le colis peut vous rouler


C'est ce que fait ember-data-react , en ouvrant la célèbre vidéo pendant l'installation. Malheureusement, il ne sera pas possible de transférer des données d'Ember vers React avec son aide - il n'y a pas une seule ligne de code javascript en elle.


12. Il se peut qu'il ne s'installe tout simplement pas.


image
Dépendances inexistantes, versions incorrectement spécifiées, référentiels privés tombés dans l'oubli - vous ne pouvez pas installer environ 0,6% de tous les packages du référentiel npm.


Au lieu d'une conclusion


Les packages NPM peuvent faire des choses étranges avec votre système, et vous n'avez pas beaucoup d'options pour vous protéger contre cela. Utilisez package-lock.json pour éviter les mises à jour soudaines (et assurez-vous que personne ne le déconnecte à votre insu), configurez CSP sur le frontend afin que la porte dérobée du module tiers ne puisse pas au moins fusionner les données avec son auteur. Et sauvegardez vos photos, au cas où.


Si vous sentez que vous avez suffisamment de force pour vous immerger dans le monde merveilleux des packages npm - vous pouvez trouver toutes les sources ici: https://github.com/malicious-packages/core . L'utilitaire est plein de hacks et de solutions non optimales, mais il fait face à sa tâche. Il y a également un vidage MongoDB dans le référentiel avec les résultats d'analyse de plus de 180 000 packages, surtout, n'oubliez pas d'ajouter le filtre {'reports.status': 'unverified'} . Je ne prévois plus de développer ce projet par manque de temps, mais je vais essayer de répondre à toutes les questions et problèmes, le cas échéant.


Prenez soin de vous et de vos applications!

Source: https://habr.com/ru/post/fr436132/


All Articles