- Im NPM-Repository wurden mehr als 100 bösartige Pakete zum Diebstahl von Zugangsdaten hochgeladen, die seit August unentdeckt blieben und zusammen mehr als 86.000 Mal heruntergeladen wurden
- Das Sicherheitsunternehmen Koi berichtet, dass eine als „PhantomRaven“ bezeichnete Angriffskampagne die NPM-Funktion Remote Dynamic Dependencies (RDD) missbrauchte, um 126 bösartige Pakete zu verbreiten
- RDD ist eine Struktur, die es Paketen erlaubt, Abhängigkeitscode dynamisch von nicht vertrauenswürdigen Domains herunterzuladen, wodurch sie von statischen Analysewerkzeugen nicht erkannt wird
- Die Angreifer nutzten diese Funktion, um bösartigen Code über HTTP-Verbindungen herunterzuladen; in den Paketmetadaten wurde dennoch „0 Dependencies“ angezeigt, sodass Entwickler und Security-Scanner dies nicht bemerkten
- Diese strukturelle Schwachstelle macht die Grenzen des Sicherheitsmanagements im NPM-Ökosystem und die Risiken automatischer Installationsmechanismen deutlich
Ausbreitung bösartiger Pakete im NPM-Repository
- Angreifer luden seit August mehr als 100 Pakete zum Diebstahl von Zugangsdaten hoch, indem sie strukturelle Schwächen des NPM-Code-Repositorys ausnutzten
- Die meisten Pakete wurden verbreitet, ohne entdeckt zu werden; die kumulierte Zahl der Downloads lag bei mehr als 86.000
- Das Sicherheitsunternehmen Koi bezeichnete diesen Angriff als PhantomRaven-Kampagne und analysierte, dass eine bestimmte NPM-Funktion missbraucht wurde
- Laut Koi befanden sich von den 126 bösartigen Paketen zum Zeitpunkt der Artikelerstellung noch etwa 80 weiterhin auf NPM
Die verwundbare Struktur von Remote Dynamic Dependencies (RDD)
- RDD ist eine Funktion, die es Paketen erlaubt, Abhängigkeitscode dynamisch von externen Websites herunterzuladen
- Normalerweise werden Abhängigkeiten über die vertrauenswürdige Infrastruktur von NPM bezogen, doch RDD erlaubt Downloads auch über unverschlüsselte Verbindungen wie HTTP
- Die PhantomRaven-Angreifer konfigurierten dies so, dass Code von einer bösartigen URL heruntergeladen wurde, etwa
http://packages.storeartifact.com/npm/unused-imports- Diese Abhängigkeiten sind für Entwickler und Security-Scanner unsichtbar und werden in den Paketinformationen als „0 Dependencies“ angezeigt
- Durch die automatische Installationsfunktion von NPM werden solche „unsichtbaren“ Abhängigkeitscodes automatisch ausgeführt
Grenzen bei der Erkennung durch Security-Tools
- Oren Yomtov von Koi sagte, PhantomRaven sei „ein Beispiel dafür, wie die blinden Flecken bestehender Sicherheitswerkzeuge raffiniert ausgenutzt werden“
- RDD wird von statischen Analysewerkzeugen nicht erkannt
- Dadurch konnten die Angreifer Sicherheitsprüfungen umgehen und bösartigen Code verbreiten
Zusätzliche Risikofaktoren
- Koi erklärt, dass über RDD geladene Abhängigkeiten bei jeder Installation erneut vom Server der Angreifer heruntergeladen werden
- Da es weder Caching noch Versionsverwaltung gibt, kann selbst bei demselben Paket je nach Installationszeitpunkt unterschiedlicher bösartiger Code eingeschleust werden
- Diese Struktur dynamischer Downloads erschwert die Integritätsprüfung von Paketen
Struktur und Hintergrund von NPM
- NPM ist ein Paketmanager für JavaScript, verwaltet von npm, Inc., einer GitHub-Tochter
- Er ist der Standard-Paketmanager für Node.js und besteht aus einem Kommandozeilen-Client und der npm registry
- In der Registry werden öffentliche sowie kostenpflichtige private Pakete gespeichert; sie können über die Website durchsucht werden
- Der Vorfall gilt als Beispiel dafür, dass die automatische Abhängigkeitsverwaltung von NPM für Angriffe missbraucht werden kann
Sonstige Erwähnungen
- Am Ende des Artikels wird die Ansicht erwähnt, dass unnötige Ausführung von JavaScript blockiert werden sollte
- Zugleich wird darauf hingewiesen, dass dieser Angriff sogar essenziellen JavaScript-Code missbrauchte
2 Kommentare
Ich habe ein Echtzeit-Scanner-Skript erstellt.
Im Pfad des verdächtigen Repositorys
npx sha1-hulud-scannereingeben.
Quellcode: https://github.com/developerjhp/sha1-hulud-scanner
Hacker-News-Kommentare
Ich habe mir inzwischen einen Alias eingerichtet, der den
npm-Befehl innerhalb eines Docker-Containers ausführtSo werden meine Umgebungsvariablen nicht offengelegt, es gibt keinen Zugriff auf Dateien außerhalb des aktuellen Verzeichnisses, und auch Konfigurationsdateien wie
.bashrcsind nicht erreichbarSiehe auch: Run tools inside Docker
npmlädt schließlich ohnehin beliebigen Code herunter, der direkt ausgeführt wirdIch würde stattdessen
pnpmempfehlen. Dort werden Lifecycle-Skripte standardmäßig nicht ausgeführt, und man kann erlaubte Skripte per Whitelist festlegenWer echten Schutz will, muss nicht nur die Installation, sondern die gesamte Ausführung in einer Sandbox laufen lassen
Nur post-install zu blockieren ist, wie es heute oft gemacht wird, bloß eine halbe Maßnahme. Supply-Chain-Angriffe werden immer gefährlicher
Wenn
neovimodervscodekompromittiert sind, kann man mit Benutzerrechten bereits genug Schaden anrichtenEin einfacher Alias funktioniert bei
node/npm, ist aber auf andere Programme schwerer anzuwenden, weil man die nötigen Ressourcen in den Container mounten mussIch habe mich das schon lange gefragt. Warum führen Leute völlig selbstverständlich
npmdirekt auf ihrem System aus?Aus Sicht von jemandem, der an reproduzierbare Builds mit
makegewöhnt ist, war es schockierend, dassnpmjedes Mal etwas anderes herunterlädt und andere Ergebnisse liefertSogar die CSS-Erzeugung an npm-Abhängigkeiten zu hängen, fand ich seltsam. Deshalb habe ich versucht, die gesamte npm-Umgebung in Docker einzufrieren, aber es fühlt sich letztlich wie ein aussichtsloser Kampf an
maven,nuget,pip,npm— alle gleichWürde man wie früher nur auf Paketmanager der Distribution setzen, wäre das heutige schnelle Ökosystem kaum möglich gewesen
Allerdings entstehen inzwischen neue Paketmanager mit stärkerem Sicherheitsfokus. Nur das Mittel zu kritisieren, ohne den Grund zu verstehen, ist nicht richtig
npmper Docker eingefroren hast, würde ich fragen, ob du diese Umgebung nach jedem Dependency-Update auch validiert hastTatsächlich pinnen
npmundpnpmAbhängigkeiten schon standardmäßig über Lockfilesnpm install thing“ zu einfach und zu billig geworden istViel Open Source wird mit Code für den Lebenslauf statt für Qualität gefüllt und landet am Ende dabei, Werbetracker großer Konzerne oder Wallet-Apps zu bauen
npm installlädt nicht einfach nur Pakete herunter, sondern führt Code ausDie Hooks preinstall, install und postinstall in
package.jsonwerden tatsächlich ausgeführtAus welchem legitimen Grund müsste der Installationsprozess überhaupt beliebige Befehle ausführen?
Relevanter Bericht: PhantomRaven npm malware
Ein weiterer Fall: Socket.dev blog
Zum Beispiel führen Linux-Kernel-Pakete nach der Installation Post-Install-Skripte aus, um initramfs neu zu erzeugen und GRUB zu aktualisieren
Die meisten DEB-/RPM-Pakete enthalten solche Skripte. Das Problem liegt also im Design selbst
npmjeder Pakete hochladen kannLinux-Distributionen haben ein vertrauenswürdiges Maintainer-System und bauen teils selbst eine Root of Trust auf Basis von PGP auf
Dagegen sind
npm,pip,rubygems,cargound ähnliche im Grunde nur eine elegantere Version von „curl | bash“Solche Post-Install-Builds waren nötig, um den Wartungsaufwand zu reduzieren
Package.swifttatsächlich ausSoweit ich gehört habe, ist das aber stark sandboxed, sodass Missbrauch schwierig ist
Siehe: SwiftPM docs, PackageDescription
pnpm v10standardmäßig alle Lifecycle-Skripte, und der Nutzer muss sie explizit erlaubenZugehörige Diskussion
Wenn man sich die jüngsten
npm-Angriffe ansieht, fragt man sich langsam, ob Entwicklung mitnpmüberhaupt noch sicher istJedes Mal, wenn ich ein React-Projekt starte, werden Hunderte Pakete installiert, und ich habe keine Ahnung, was die eigentlich tun
Im Backend installiert man explizit nur das, was man braucht, aber das Frontend wirkt wie eine Büchse der Pandora voller Schwachstellen
npmist nur das größte und daher am häufigsten in den Nachrichtenjjinstalliert habe, wurden 470 Pakete installiert, bei Pythonswan2gpwaren es 211. Am Ende ist das überall ähnlichWie beim
xz-Vorfall hängen die einzelnen Abhängigkeiten oft an irgendwelchen zufälligen Privatpersonen, und man muss darauf vertrauen, dass sie nicht Opfer von Social Engineering werdenPyPIist nicht sicher. Es gab Fälle, in denen durch kompromittierte GitHub Actions bösartiger Code in legitime Pakete eingeschleust wurdeJedes Mal, wenn ich mit Frameworks wie Angular oder Vue entwickle, macht mich das nervös
Wenn ich die Tausenden Abhängigkeiten in
node_modulessehe, fühlt es sich wie ein Vorbote einer Katastrophe anWenn nur ein einziger Open-Source-Entwickler auf Phishing hereinfällt, kann sofort alles kompromittiert sein
Das JavaScript-Ökosystem ist grundlegend kaputt. Ein einziger Tippfehler kann einen Supply-Chain-Angriff auslösen
Bei NuGet oder Maven geht das zwar auch, aber dort ist die Standardbibliothek größer, es gibt weniger Abhängigkeiten und man hat mehr Kontrolle
Perfekt ist das nicht, aber es ist immerhin ein Schritt besser
Von den 86.000 Downloads dürften die meisten eher automatisierte Scanner oder Bots gewesen sein als echte Nutzer
Wenn man eine neue Version hochlädt, wird sie oft schon nach ein oder zwei Tagen Hunderte Male heruntergeladen, ohne dass das echte Menschen sein müssen
Das heißt: Möglicherweise gab es kaum tatsächlich infizierte Nutzer
Es gibt auch viele Angriffe, die auf Paketnamen zielen, die von AI-Chatbots halluziniert wurden. Es geht also um mehr als bloße Statistik
Eine ausführlichere Beschreibung des Angriffs gibt es in diesem BleepingComputer-Artikel
Ich frage mich, ob es eine Möglichkeit gibt, bei
npm installPakete zu erkennen oder zu filtern, die HTTP-URLs als Abhängigkeiten verwendenDa je nach Anfragendem unterschiedliche Payloads ausgeliefert werden können, ist das mit gewöhnlichen Scannern schwer zu erkennen
Als Hobbyentwickler überlege ich, wie man sich gegen solche Supply-Chain-Angriffe wappnen sollte
Wenn man bekannten Tutorials folgt und dabei Abhängigkeiten installiert, wird man irgendwann wie von selbst nachlässig bei der Sicherheit
Ich betreibe auch mehrere Dienste in meinem Homelab und mache mir Sorgen, dass dort irgendwann Bots eindringen könnten. Wo fängt man da am besten an?
Das ist keine perfekte Garantie, aber deutlich besser, als wenn gleich der ganze Server kompromittiert wird
Nur den benötigten Code direkt zu kopieren und zu verwenden, ist ebenfalls eine gute Lernmöglichkeit und oft sicherer
In so einer Struktur kann Vertrauenswürdigkeit auf Distributionsebene hergestellt werden, statt dass Millionen Nutzer alles selbst prüfen müssen
Beispiele: Hono, Zod
Ich bin kürzlich auf Bun umgestiegen, weil dort Dinge wie Datenbanktreiber oder S3-Clients bereits eingebaut sind und weniger zusätzliche Downloads nötig werden
Eine Struktur, bei der Abhängigkeiten über Lifecycle-Hooks hereingeholt werden, kann jederzeit zum Angriffsknotenpunkt werden
Selbst wenn heute noch alles sauber ist, kann es später bösartig werden, wenn der Eigentümer gehackt wird oder seine Meinung ändert
Solche Installations-Hooks in dieser Form sind letztlich ein nicht tragfähiges Design