So verhindern Sie schädliche Pakete
27. März 2016
0 Min. LesezeitLetzte Woche warnte CERT Nutzer vor den Risiken, ein schädliches npm-Paket zu veröffentlichen oder zu verwenden. Dieses erhebliche Risiko besteht nicht nur bei npm, tritt in diesem Ökosystem jedoch wahrscheinlicher auf. Dabei sollte man beachten, dass dies zwar definitiv ein Angriffsvektor ist, meiner Meinung nach aber weniger eine Sicherheitslücke als vielmehr eine unsichere Standardeinstellung.
In diesem Beitrag erfahren Sie mehr über das Risiko und wie Sie sich schützen können. Wir betrachten die Abwägungen, die zu diesem Problem geführt haben, sehen uns ein Angriffsszenario an und zeigen, wie Sie das Risiko in Ihren eigenen Umgebungen mindern können. Wenn Sie direkt zu den konkreten Maßnahmen springen möchten, lesen Sie die Abschnitte zur Risikominderung.
Vielleicht ist auch der Beitrag 10 Best Practices für npm-Sicherheit hilfreich. Dort finden Sie ein PDF mit einer herunterladbaren Checkliste sowie einen ausführlichen Artikel dazu, wie Sie Sicherheitsrichtlinien und sichere Praktiken für npm umsetzen.
Der Angriff
Schädliche Pakete in 5 einfachen Schritten
Das Kernproblem ist, wie einfach sich ein neues Paket veröffentlichen lässt. Wie git, pip und andere ermöglicht npm es Nutzern, ihre Anmeldedaten in einer Dotdatei (.npmrc) zu speichern und anschließend ohne interaktive Abfragen Pakete zu veröffentlichen.
Leider ist dies ein Fall, in dem etwas zu einfach gemacht werden kann. Der optimierte Veröffentlichungsprozess erhöht die Wahrscheinlichkeit, dass versehentlich ein Paket veröffentlicht wird. Noch wichtiger ist jedoch, dass er Angreifern die Möglichkeit eröffnet, absichtlich schädlichen Code zu veröffentlichen. Um eine schädliche Paketversion zu veröffentlichen, muss ein Angreifer lediglich Folgendes tun:
Code auf dem Rechner eines Entwicklers ausführen.
Ermitteln, welcher npm-Nutzer angemeldet ist (
npm whoami --silent)Eines der Pakete des Nutzers in einen temporären Ordner herunterladen
package.json bearbeiten: einen schädlichen
postinstall-Hook hinzufügen und die Versionsnummer um 0.0.1 erhöhenVeröffentlichen (
npm publish)
Der einzige schwierige Schritt ist der erste. Leider gehen die meisten Entwickler ziemlich nachlässig mit ihren Umgebungen um …
Haben Sie schon einmal etwas mit curl X | bash installiert? Das ist eine Möglichkeit für Angreifer, sich Zugang zu verschaffen – sie brauchen nicht einmal sudo bash. Oder installieren Sie vielleicht gelegentlich lokal ein npm-Paket, um es auszuprobieren? Jede einzelne seiner Abhängigkeiten kann einen postinstall-Hook ausführen, der die oben beschriebenen Schritte durchführt.
Tatsache ist: Wir Entwickler experimentieren – und verwenden daher ganz natürlich keine makellosen Umgebungen. Solche Umgebungen sollten keine Veröffentlichungsrechte haben.
Schnelle Verbreitung, langsame Erkennung
Sobald der Angreifer fertig ist, kann er sich entspannt zurücklehnen, während sich sein Code im Node-Ökosystem verbreitet. Die meisten Nutzer dieses Pakets laden es mit einem Semver-Bereich, der implizit auch Patch-Versionen (0.0.X) einschließt, und beziehen so die neue Version, ohne es zu merken. Angreifer können den schädlichen Code auch auf Pakete übertragen, die den Opfern gehören. So entsteht ein sich noch schneller verbreitender Wurm.
Erschwerend kommt hinzu: Wenn ein solches schädliches Paket veröffentlicht wurde, lässt sich das nur schwer erkennen. npm benachrichtigt Nutzer nicht, wenn eine neue Version veröffentlicht wird, und es gibt keine einfache Möglichkeit, Unterschiede zwischen Paketen zu erkennen (anders als bei git). Am ehesten fällt Ihnen ein solcher Vorfall auf, wenn Sie die neue Versionsnummer bemerken. Wenn Sie ein Projekt allein aktiv betreuen, werden Ihnen Versionsänderungen wahrscheinlich auffallen. Bei ruhenden Projekten oder Projekten, an denen ein ganzes Team arbeitet, können sie jedoch leicht unbemerkt bleiben.
Maßnahmen zur Risikominderung
So verhindern Sie schädliche Veröffentlichungen (öffentliche Pakete)
Wenn Sie an einem npm-Paket mitarbeiten, liegt es in Ihrer Verantwortung, sich zu schützen. Lassen Sie nicht zu, dass Angreifer in Ihrem Namen eine schädliche Version veröffentlichen. Das ist ganz einfach: Bleiben Sie abgemeldet.
Veröffentlichen Sie Pakete ausschließlich über Ihre CI, wenn ein Build auf dem Master-Branch erfolgreich ist. Verwenden Sie dafür semantic-release oder eigene Skripte. Die Schritte im Einzelnen:
Widerrufen Sie alle aktuellen Tokens. Das können Sie auf Ihrer Token-Seite tun. Gehen Sie auch bei allen Mitwirkenden so vor.
Richten Sie ein neues Token in Ihrer CI ein. Remy hat eine ausführliche Anleitung für Travis geschrieben, aber die meisten CI-Systeme unterstützen verborgene Variablen. Beachten Sie: Sobald Ihr Token eingerichtet ist, wird es durch
npm logoutungültig. Löschen Sie stattdessen die Datei~/.npmrc, um sich abzumelden.Verwenden Sie für Entwicklungsversionen git. Wenn Nutzer auf eine temporäre Paketversion zugreifen müssen (z. B. zur Fehlerbehebung), übertragen Sie sie in einen Branch und zeigen Sie ihnen, wie sie sie über einen git-Commit installieren.
So verhindern Sie schädliche Veröffentlichungen (private Pakete)
Wenn Sie ein privates Paket verwenden, können Sie nicht abgemeldet bleiben, da Sie angemeldet sein müssen, um auf Ihre privaten Pakete zuzugreifen. Zum Glück hat npm vor Kurzem Organisationen eingeführt und unterstützt nun Nutzer mit schreibgeschütztem Zugriff. So können Sie Zugriff gewähren, ohne das Risiko einer Veröffentlichung einzugehen.
Hier noch einmal die einzelnen Schritte:
Erstellen Sie eine npm-Organisation. Wenn Sie nur einen Nutzer haben, steigen dadurch die Mindestkosten um 7 $ pro Monat – die Investition lohnt sich jedoch.
Erstellen Sie ein Team mit schreibgeschütztem Zugriff auf Ihre Pakete oder Ihren Scope.
Fügen Sie Nutzer als Mitglieder zu diesem Team hinzu. Sie können auch einen einzelnen Nutzer mit schreibgeschütztem Zugriff für alle verwenden.
Melden Sie Ihr Team und sich selbst mit diesen schreibgeschützten Nutzern an.
Diese Schritte machen es zwar nicht überflüssig, bei der Installation beliebiger Software auf Ihrem Computer vorsichtig zu sein. Sie verringern aber zumindest die Wahrscheinlichkeit, dass Sie schädlichen Code weiterverbreiten.
So schützen Sie sich vor schädlichen Paketen
Als Nutzer von npm-Paketen können Sie dieses Risiko nicht vollständig vermeiden (das gilt auch für andere Paketmanager). Die einzige Möglichkeit, das Risiko zu mindern, besteht darin, die Pakete, die Sie installieren, genau zu kontrollieren.
Wenn Sie lokal entwickeln, sollten Sie npm shrinkwrap verwenden, um die von Ihnen verwendeten Paketversionen festzuschreiben. shrinkwrap fixiert die verwendeten Versionen und bezieht keine neuen, sofern Sie dies nicht ausdrücklich anfordern. So können Sie jedes Update prüfen und manuell bewerten. Das ist zwar umständlich, erhöht aber Ihre Sicherheit.
Wenn Sie für ein Unternehmen arbeiten, sollten Sie npm On-Site verwenden und nur zulässige Pakete auf eine Whitelist setzen. Auch das ist etwas umständlich, verringert aber das Risiko, dass schädliche Pakete in Ihre Umgebung gelangen. Damit Sie hier wirklich geschützt sind, müssen Sie Read through cache auf Off setzen.
Beide Lösungen verlangsamen die Nutzung neuer Versionen. Dadurch sind Sie möglicherweise weiterhin anfällig, wenn Sicherheitslücken in älteren Versionen dieser Pakete bekannt werden. Wenn Sie sich dafür entscheiden, sollten Sie bekannte Sicherheitslücken in Ihren npm-Abhängigkeiten im Blick behalten, zum Beispiel, indem Sie Snyk verwenden.
Kann npm das nicht einfach beheben?
Wäre es nicht großartig, wenn npm einfach ein oder zwei Funktionen ergänzen könnte, um dieses ganze Risiko zu beseitigen?
Leider ist das nicht möglich. Dieses Risiko ergibt sich ganz natürlich aus der Verwendung von Open-Source-Paketen. Dabei nutzen wir viele kleine Codebausteine, die von vielen verschiedenen Menschen geschrieben wurden. Das steigert zwar die Produktivität, bedeutet aber auch, dass wir in hohem Maße von den Autoren dieser Pakete und ihren Absichten abhängig sind.
Wichtig ist auch, dass dieses Verhalten nicht nur bei npm auftritt. Die meisten anderen Paketmanager ermöglichen eine stille Veröffentlichung, und praktisch alle lassen zu, dass benutzerdefinierter Paketcode bei der Installation ausgeführt wird. Das Risiko ist bei npm nur deshalb größer, weil dort mehr indirekte Abhängigkeiten verwendet werden. Dadurch ist es praktisch unmöglich, sie alle manuell nachzuverfolgen.
Dennoch würde ich mir wünschen, dass das npm-Team einige Dinge umsetzt, um Folgendes zu erreichen:
Alle Mitwirkenden per E-Mail benachrichtigen, wenn eine neue Paketversion veröffentlicht wird. Das sollte standardmäßig aktiviert sein; Nutzer könnten sich später bei Bedarf abmelden.
Bei
npm publishAnmeldedaten verlangen, sofern nicht ausdrücklich ein Automatisierungstoken erstellt und verwendet wurde. Dadurch wird das Standardverhalten (mitnpm login) sicherer. Wahrscheinlich wäre dies eine inkompatible Änderung; daher ist vor npm 4 wohl nicht damit zu rechnen.Wenn möglich, die Aktionen einschränken, die Installationsskripte während der Installation ausführen können. Dadurch verschwindet das Risiko zwar nicht, aber ein Angriff wird schwieriger und damit unwahrscheinlicher.
Starten Sie mit Capture-the-Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.


