Skip to main content

Dateisystem-Übernahme durch Schwachstellen im npm-JavaScript-Paketmanager verstehen

Artikel von
prioritize vulns header

7. Januar 2020

0 Min. Lesezeit

Am 11. Dezember 2019 wurde eine Sicherheitslücke öffentlich bekannt gemacht, die alle wichtigen JavaScript-Paketmanager (npm, yarn und pnpm) betrifft. Die vom Sicherheitsforscher Daniel Ruf entdeckte Schwachstelle ermöglicht es Angreifern, mit verschiedenen Methoden beliebige Dateien zu überschreiben.

In diesem Artikel:

Wie funktionieren Node.js-Kommandozeilenpakete?

npm-Pakete enthalten häufig einen bin-Schlüssel in der Paketmanifestdatei – package.json. Der Paketmanager-Client – zum Beispiel npm oder eine Alternative – verwendet diesen bin-Schlüssel, um ausführbare Dateien zu deklarieren, die über die globale Umgebungsvariable $PATH in Ihrer Eingabeaufforderung verfügbar sind.

Wahrscheinlich ist Ihnen diese Funktion schon begegnet, wenn Sie Kommandozeilenpakete global installiert haben – etwa Angular CLI über @angular/cli, typescript oder die Snyk CLI über snyk —. Diese sind dann unabhängig von einem bestimmten npm-Projektverzeichnis überall in Ihrem Pfad verfügbar. Um zu verstehen, wie der bin-Schlüssel verwendet wird, sehen wir uns mit unpkg an, wie das Angular-CLI-Projekt funktioniert. Dazu rufen wir die package.json auf der unpkg-Website auf.

Die package.json-Datei von @angular/cli hebt den bin-Schlüssel hervor, der den Befehl ng ./bin/ng zuordnet.
ng-cli package.json-Feld, das die Verwendung des JSON-Schlüssels „bin“ zeigt, um eine ausführbare Datei zu definieren, wenn npm dieses Paket installiert (Quelle: unpkg https://unpkg.com/browse/@angular/cli)

Wie oben zu sehen ist, deklariert die Manifestdatei package.json in dieser Paketversion eine ausführbare Datei namens ng, die auf eine im Paket enthaltene Datei unter ./bin/ng verweist.

Diese JavaScript-Datei ./bin/ng wird für den Benutzer ausführbar gemacht, indem am Anfang der Datei eine Unix-Shebang-Anweisung angefügt wird. Diese Anweisung teilt der Shell mit, welcher Interpreter zum Ausführen der Datei verwendet werden soll. Bei Node.js-Anwendungen ist die Node.js-Binärdatei auf dem Betriebssystem des Benutzers installiert.

Im Fall von Angular CLI ist der Inhalt der ausführbaren Datei in der folgenden Abbildung zu sehen:

Quellcode der ausführbaren Datei ng der Angular CLI mit einer Node.js-Versionsprüfung und einer Fehlermeldung für nicht unterstützte Versionen.
(Quelle: https://unpkg.com/browse/@angular/cli@6.0.4/package.json)

Wie wirkt sich diese Sicherheitslücke auf den npm-Paketmanager-Client aus?

Um die Auswirkungen dieser Schwachstelle zu verstehen, müssen wir uns npm etwas genauer ansehen – insbesondere die Mechanismen, mit denen npm dafür sorgt, dass installierte ausführbare Dateien für Benutzer verfügbar sind.

Der npm-Client verwaltet deklarierte ausführbare Dateien („Bins“) global installierter Pakete in einem bestimmten Verzeichnis. Dort legt er symbolische Links von den ausführbaren Dateien dieser Pakete zu Links im genannten Verzeichnis an.

Um herauszufinden, welches Verzeichnis für diese ausführbaren Dateien verwendet wird, gehen Sie mit dem npm-Client wie folgt vor:

$ npm bin --global
/Users/lirantal/.nvm/versions/node/v10.16.3/bin

Wenn Sie die in Ihrer Shell verfügbare Umgebungsvariable $PATH prüfen, finden Sie einen Eintrag, der dem Verzeichnis für Ihr Betriebssystem entspricht. So können Sie von jedem Verzeichnis im Betriebssystem aus auf global installierte Pakete mit deklarierten ausführbaren Dateien zugreifen.

Mit diesen Informationen stellt sich unweigerlich die Frage, ob ein Paket eine ausführbare Datei deklarieren kann, die von einem anderen Paket bereitgestellt wird. Genau das wollte Daniel herausfinden. Dabei entdeckte er Schwachstellen, durch die sich beliebige Dateien in den wichtigen Paketmanagern npm, yarn und pnpm überschreiben lassen.

Wie lässt sich diese npm-Sicherheitslücke in der Praxis ausnutzen?

Bei Snyk reproduzieren wir diese Schwachstelle zum Schreiben beliebiger Dateien und zeigen, wie sie ausgenutzt werden kann. Dabei nutzen wir die Proof-of-Concepts von Daniel, die er dem Snyk-Sicherheitsteam zur Verfügung gestellt hat.

Das erste Paket definiert global ausführbare Dateien wie folgt:

{
  "name": "binary-replacer",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Daniel Ruf <mac1@daniel-ruf.de>",
  "license": "MIT",
  "bin": {
    "curl-test": "./bin/index.js",
  }
}

Dabei gibt die ausführbare Datei curl-test einfach Text in der Konsole aus:

#!/usr/bin/env node
console.log('hi')

Wenn wir dieses Paket global mit npm install -g binary-replace installieren und anschließend den Befehl curl-test in der Shell ausführen, sollte hi auf dem Bildschirm erscheinen.

Stellen Sie sich nun ein weiteres Paket vor: binary-replacer-2. Auch dieses definiert eine ausführbare Datei und verwendet denselben bin-Schlüssel wie das vorherige Paket: curl-test

{
  "name": "binary-replacer-2",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Daniel Ruf <mac1@daniel-ruf.de>",
  "license": "MIT",
  "bin": {
    "curl-test": "./bin/index.js",
  }
}

Sobald der Benutzer dieses Paket global installiert, überschreibt npm den vorherigen symbolischen Link mit der vom neuen Paket bereitgestellten ausführbaren Datei. In diesem Beispiel ist diese harmlos:

#!/usr/bin/env node
console.log('hi 2')

Was aber, wenn ein schädliches Paket auf einige der bekannteren global verwendeten Pakete abzielt? Die Möglichkeiten sind vielfältig – vom Paket now von Zeit bis zur CLI fkill von Sindre Sorhus.

Außerdem hat Daniel zahlreiche Varianten dieser Schwachstelle in npm, yarn und pnpm aufgezeigt. Was wäre zum Beispiel, wenn der Schlüssel statt curl-test einen relativen Linkpfad enthielte?

 "bin": {
    "../../aaa": "/bin/date"
  }

Oder wenn der Schlüssel auf einen absoluten Pfad zu einem bekannten Kommandozeilentool gesetzt würde, das häufig von Benutzern in einer Shell-Eingabeaufforderung verwendet wird, etwa:

"bin": {
  "/usr/bin/date": "./fake-date"
}

Es ist bemerkenswert, dass pnpm unter der Leitung des alleinigen Entwicklers Zoltan Kochan in den meisten Fällen das Richtige tut und nur dann anfällig ist, wenn ein relativer Pfad angegeben wird. Das ist trotzdem ein Problem. Ein Upgrade auf korrigierte npm-Versionen ist ebenfalls möglich.

Warum ist diese npm-Sicherheitslücke so schwerwiegend?

Die Schwachstelle ist besonders gravierend, weil beliebige Dateien auch dann überschrieben werden können, wenn Pakete mit dem npm-Kommandozeilenflag —ignore-scripts installiert werden. Man könnte erwarten, dass dadurch verhindert wird, dass schädliche Binärdateien auf diese Weise vorgehen.

Darüber hinaus ist dieser Angriff nicht nur bei global installierten Paketen und ihren ausführbaren Dateien relevant, sondern ebenso bei transitiven Abhängigkeiten in Ihrem Projekt. Werden Abhängigkeiten mit einem gewöhnlichen npm install installiert, kann ein Paket beliebige Dateien innerhalb und außerhalb des Projektverzeichnisses überschreiben. Dies kann unter anderem zum Einschleusen von Malware, zu einem Angriff durch Manipulation von Lockfiles oder auf andere Weise zur Manipulation des Dateisystems führen.

Bin ich betroffen, und was sollte ich tun?

In zwei Fällen besteht für Sie das Risiko, betroffen zu sein:

  1. Sie installieren ein schädliches Paket – entweder, weil Sie durch Social Engineering dazu verleitet wurden, oder weil ein Angreifer beliebte Pakete durch Typosquatting imitiert und Sie eines davon installieren.

  2. Ein nicht schädliches Paket wird kompromittiert und seine package.json-bin-Schlüssel werden so geändert, dass sie Dateien überschreiben und zugleich eine schädliche Datei zur Ausführung einschließen. Das ist zwar sehr unwahrscheinlich, ist aber bereits zweimal vorgekommen: [1], [2]

Die Auswirkungen dieser Schwachstelle führten auch zu Sicherheitsupdates für Node.js, da der npm-Paketmanager-Client mit Node.js ausgeliefert wird und ein Update auf die korrigierte npm-Version 6.13.4 erforderlich war.

Daniel meldete die Erkenntnisse zur Sicherheitslücke zunächst dem Snyk-Sicherheitsforschungsteam, um die koordinierte, verantwortungsvolle öffentliche Offenlegung bei allen Projekten und Maintainerinnen und Maintainer der betreffenden Paketmanager zu unterstützen. Weitere Informationen zu den Angriffsarten veröffentlichte er in seinem Blog.

Wenn Sie eine der folgenden Versionen von npm, yarn oder pnpm verwenden, sind Sie gefährdet und sollten unbedingt sofort ein Upgrade durchführen:

Es kommt zwar nicht häufig vor, dass npm, yarn oder pnpm als Projektabhängigkeit eingebunden werden. Wenn Snyk Ihr Projekt jedoch überwacht und anfällige Versionen dieser Paketmanager findet, werden Sie durch die regulären Snyk-Warnmeldungen benachrichtigt. Wenn Sie außerdem Ihr GitHub-Repository verbunden haben (oder Bitbucket), erstellen wir automatisch einen Pull Request, damit Sie ein Upgrade auf korrigierte Versionen dieser Paketmanager durchführen können.

Wir empfehlen Ihnen außerdem, beim Umgang mit Paketmanagern wie npm sichere Entwicklungspraktiken anzuwenden. Damit es Ihnen leichter fällt, haben wir Sicherheitsrichtlinien und Best Practices zusammengestellt, die Sie unter 10 npm-Sicherheits-Best-Practices finden.

Glauben Sie, eine Schwachstelle in einem Open-Source-Paket entdeckt zu haben? Wir bei Snyk schätzen die Security-Community und sind überzeugt, dass eine verantwortungsvolle Offenlegung von Sicherheitslücken in Open-Source-Paketen dazu beiträgt, die Sicherheit und Privatsphäre der Nutzer zu gewährleisten. Wenn Sie glauben, eine Schwachstelle in einem Open-Source-Paket entdeckt zu haben, können Sie sie über das Snyk Open Source Package Vulnerability Disclosure program melden. Wir kümmern uns dann um den Rest! https://snyk.io/vulnerability-disclosure/

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.

Weiterlesen

AI Background min crop
Blog

KI ruft alle Risiken auf den Plan, die Sie akzeptiert haben: Sieben Erkenntnisse aus dem AI Security Panel: Unfiltered

KI macht Angriffe günstiger und schneller und legt Risiken offen, die Unternehmen bereits tragen. Vier Sicherheitsverantwortliche erklären, warum Abwehr in Maschinengeschwindigkeit und schnellere Behebung jetzt unverzichtbar sind.

blog feature ai violet
Blog

VulnBump: Können KI-Agenten anfällige Abhängigkeiten beheben, ohne den Build zu beschädigen?

VulnBump testet KI-Agenten anhand von 307 realen Upgrades von Abhängigkeiten. Eine Behebung zählt nur, wenn die Sicherheitslücke geschlossen ist und Build und Tests weiterhin erfolgreich sind.

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSec: Sicherheit, die mit der KI-Entwicklung Schritt hält

KI-gestützte Entwicklung ist schneller als herkömmliche Sicherheitsabläufe. Snyks Agentic AppSec setzt Sicherheitsagenten ein, um Schwachstellen kontinuierlich zu finden, zu beheben und zu überprüfen – während Menschen die Maßstäbe festlegen.