Sichtbar unsichtbare schädliche Node.js-Pakete: Wenn Nischenkonfigurationen auf unsichtbare Zeichen treffen
Aviad Hahami
28. Februar 2022
0 Min. LesezeitIn den vergangenen Jahren ist die Zahl der Open-Source-Pakete, die erstellt und in freier Wildbahn eingesetzt werden, massiv gestiegen. Inzwischen hat jedes Ökosystem seinen eigenen Paketmanager – und fast jeder Paketmanager birgt verborgene Möglichkeiten und Konfigurationen.
Während Entwickler fortlaufend immer mehr Pakete installieren, wächst auch das Interesse von Angreifern an den Angriffsflächen dieser Pakete. Damit beginnt die Suche nach dem perfekten, gut getarnten schädlichen Paket.
In diesem Beitrag geht es um Angriffe auf das Node.js-Ökosystem und die Paketmanager yarn und npm. Betrachten Sie ihn jedoch auch als „Aufruf zum Handeln“: Untersuchen Sie andere Ökosysteme auf ähnliche Probleme, um das Bewusstsein dafür zu schärfen und die Sicherheit unserer Community insgesamt zu verbessern.
Doch jetzt legen wir los!
Teil 1: Nischenkonfigurationen
Neulich erzählte mir ein Forscherkollege von einigen interessanten Konfigurationsoptionen in npm, die kaum bekannt sind und schwerwiegende Auswirkungen auf die Sicherheit haben können. (Später fanden wir ähnliche Optionen für yarn.) Damit kann festgelegt werden, welche Binärdatei der Paketmanager im Projektverzeichnis ausführen soll. Ja, genau: welche Binärdatei!
In der Konfiguration sind dies yarnPath in der Datei .yarnrc sowie git, shell und script-shell in der Datei .npmrc, um nur einige zu nennen. Für den vollständigen Kontext des folgenden Angriffsvektors empfehle ich Ihnen dringend, Rotems Blogbeitrag (von Cider Security) zu diesem Fund zu lesen.
Vielleicht fragen Sie sich: „Warum werden diese Dateien (die ich gerade geklont/heruntergeladen habe) überhaupt berücksichtigt?“ Die Antwort lautet: So funktionieren npm und yarn. Im Rahmen der Projektverarbeitung durchsucht der Paketmanager .rc-Dateien hierarchisch: zuerst das aktuelle Projektverzeichnis, dann das Benutzerverzeichnis und schließlich das Stammverzeichnis. Weitere Informationen dazu finden Sie in der Dokumentation zur NPM-Konfiguration.
Mit den oben genannten Optionen können wir also ein teilweise getarntes schädliches Paket erstellen (in Repositories oder Tarballs, da `.rc`-Dateien beim Ausführen von `npm install` oder einem entsprechenden Befehl nicht heruntergeladen werden). Dazu verwenden wir die folgende .yarnrc-Datei als Konfiguration:
(Hinweis: Dieses Beispiel verwendet eine .yarnrc-Datei. Eine ähnliche .npmrc-Datei mit der entsprechenden Konfigurationsoption führt jedoch zum selben Ergebnis.)
Dadurch wird bei jedem Aufruf von yarn install im Stammverzeichnis des oben genannten Projekts evil.sh ausgeführt. Jetzt müssen wir nur noch die schädliche Datei hinzufügen.
Zwei wichtige Hinweise:
Auch wenn Sie
--ignore-scriptsoder eine entsprechende Anweisung angeben, wird das oben beschriebene Verhalten weiterhin ausgelöst.Ist ein solches Paket eine Abhängigkeit Ihres Projekts, wird die schädliche .yarnrc-Datei nicht berücksichtigt, da sie sich in
node_modulesbefindet und keine gleichrangige Datei ist. In diesem Fall besteht also keine Gefahr.
Teil 2: Code vor aller Augen verbergen
Ein weiteres heißes Thema des vergangenen Jahres war Trojan Source Code – also schädlicher Code, der durch Zeichen mit anderen Unicode-Werten entsteht, als es ihrem üblichen Erscheinungsbild entspricht.
Das Prinzip ist recht einfach: Einige Zeichen (keine Leerzeichen, CR, LF usw.) werden beispielsweise als Leerraum dargestellt, sind aber dennoch gültige Zeichenfolgen.
Ein etwas genauerer Blick: Das scheinbar leere Zeichen „ “ (hexadezimal 0x3164) heißt „HANGUL FILLER“. Wie Sie (nicht) sehen können, ist es kein Leerzeichen, sondern ein gültiger „Buchstabe“. Damit können wir bestimmte Logik in Codeausschnitten verbergen und bei der Einführung schädlichen Codes unentdeckt bleiben.
Für unsere Demonstration reichen die obigen Informationen aus, deshalb gehe ich nicht weiter auf das Thema ein. Wenn Sie mehr Informationen, Kontext und Beispiele wünschen, empfehle ich Ihnen dringend, Folgendes zu lesen:
Teil 3: Verborgene Binärdateien + verborgene Konfigurationen = RCE
Nachdem wir die Grundlagen geklärt haben, sind die nächsten Schritte unseres Angriffs einfach:
Erstellen Sie ein scheinbar harmloses Paket.
Erstellen Sie eine schädliche Datei mit einem verborgenen Zeichen im Namen.
Erstellen Sie eine .rc-Datei.
Legen Sie den Konfigurationsparameter so fest, dass er auf den Binärdateinamen mit dem unsichtbaren Zeichen verweist.
Nach diesen Schritten sind wir bereit. Betrachten wir den Angriff nun aus Sicht der Opfer:
Wenn ein Entwickler auf ein solches Paket stößt, ohne den Angriffsvektor zu kennen, wird er die Warnsignale wahrscheinlich übersehen.
Vielleicht ist er etwas vorsichtig und führt ls -l aus. Dann sieht er Folgendes:
Da die Ausgabe nicht ungewöhnlich wirkt, ist dies die erste Falle. Die meisten Betroffenen führen an diesem Punkt yarn install aus und werden zum Opfer.
Nehmen wir jedoch an, unser Ziel ist ein erfahrener Entwickler, der in ls. das Flag „unsichtbare Zeichen anzeigen“ ergänzt. Das ergibt:
Nun fragt sich das Ziel vielleicht: „Okay, was steht in der .rc-Datei?“ (und ignoriert dabei völlig die unauffällige, unsichtbare Datei) und zeigt sie mit cat an. Das Ergebnis:
Das ist die zweite Falle.
Den meisten Entwicklern ist nicht bewusst, dass yarn (oder npm) benutzerdefinierte Binärdateien aufrufen kann. Etwas wie die obige Ausgabe wirkt zwar merkwürdig, aber dort steht doch nicht „evil.sh“, oder?
Die dritte Falle ist ganz einfach: Das Ziel sieht die Datei schlicht nicht. Selbst wenn es die .rc-Datei entdeckt und sich die yarn-path-Spezifikation ansieht (dasselbe gibt es auch bei npm), könnte es annehmen, dass die Eigenschaft ins Leere verweist, und anschließend doch den Paketmanager aufrufen.
In meinem PoC führt yarn install zu folgendem Ergebnis:
Schutzmaßnahmen und Überlegungen
So können Sie sich schützen:
Vertrauen Sie niemals Code aus Drittquellen. Vergewissern Sie sich stets, was Sie geklont oder heruntergeladen haben, und achten Sie auf ungewöhnliches Verhalten und merkwürdige Konfigurationen.
Führen Sie Code in einer Sandbox aus. Führen Sie Code aus Drittquellen stets in einer Sandbox oder containerisierten Umgebung aus. So wirkt sich ein schädliches Paket wahrscheinlich nicht auf Ihr System aus und kann Ihren Rechner nicht kompromittieren.
Hinweis: Auch die Ausführung in einer Sandbox ist möglicherweise nicht hundertprozentig sicher, da es Kernel-Schwachstellen, Sandbox-Ausbrüche usw. gibt. In einer solchen Umgebung reduzieren Sie das Risiko jedoch erheblich und blockieren die meisten einfachen Angriffe (etwa einfache Reverse-Shells oder Ähnliches).
Und damit haben wir den Angriff abgewehrt.
Das Faszinierende an diesem Angriffsvektor ist, dass er vollständig sichtbar und doch unsichtbar ist.
Vielleicht sagen Sie: „Ich führe immer ls -la aus, überprüfe alle Dateien und kenne sämtliche Konfigurationsoptionen des Paketmanagers genau.“ Gut, aber stimmt das wirklich? Und gilt das auch für alle in Ihrer Organisation?
Und wie bei Bloom-Filtern lautet die Antwort hier: „Nein heißt nein, Ja heißt vielleicht.“
Zum Schluss möchte ich nochmals betonen: Dieser Beitrag ist ein Aufruf zum Handeln – nicht zur Ausnutzung von Schwachstellen. Die Community sollte das Bewusstsein für solche Angriffsvektoren schärfen. Da alle Anwendungen entwickeln und nahezu blind Abhängigkeiten installieren, ist es entscheidend, andere auf verdächtige Konfigurationen hinzuweisen.
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.



