Dependency-Confusion-Angriff – So funktioniert er und wie man ihn verhindert

Die „php2shell“-Patches (CVE-2026-109618 und CVE-2026-109619) für PHP am Ende des Lebenszyklus (EOL) sind nun verfügbar. Da die Antworten des Vertriebs aufgrund der hohen Nachfrage derzeit langsamer als gewöhnlich ausfallen, ist der schnellste Weg zu den gepatchten Paketen der Online-Kauf von ELS für Runtimes (wird in einem neuen Tab geöffnet). Lesen Sie die FAQ zu den Patches

Gehen Sie direkt zu einer KI-Zusammenfassung dieses Blogbeitrags

  • Fasse diesen Beitrag mit Perplexity zusammen
  • Fasse diesen Beitrag mit Gemini zusammen

In der modernen Softwareentwicklung haben wir uns von einem rein auf der Lieferkette basierenden Installationsmodell zu einem hybriden Modell entwickelt. Abhängigkeiten können nun über zwei Wege bezogen werden: private und öffentliche Pakete. Dieser Artikel befasst sich mit der Verwechslung von Abhängigkeiten und deren Zusammenhang mit Angriffen über tiefe transitive Abhängigkeiten.

Das hybride Lieferkettenmodell

 

Today, we have two different ways of installing packages via various tools like npm, pnpm, etc. The concept of a single way to install packages is a thing of the past. Years ago, we would just open our terminal up and type npm install <package>. It would get pulled from the npm registry, and that would be that. Private packages, or scoped packages, can be delivered from the npm registry and are secure by default. You can also host scoped packages in internal registries like Nexus, Artifactory, and Verdaccio.

Ein Paket mit Gültigkeitsbereich sieht so aus: @myorg/mypackage. Es beginnt mit dem Symbol „@“, gefolgt vom Namen Ihrer Organisation, und endet mit einem „/“ und dem Paketnamen. Dies ist ein gesichertes, privates Paket, das in der npm-Registry gehostet wird. Dies bietet Ihnen auch die Möglichkeit, Pakete unter Ihrer Organisation zu gruppieren. Sie können weiterhin öffentliche Pakete installieren, die ebenfalls Open Source sind. Sie werden mit ziemlicher Sicherheit ein öffentliches Paket installieren, um Funktionen zu erweitern. Daher werden Sie eine Mischung aus öffentlichen und privaten Paketen haben.

Die Sicherheitslücke schleicht sich ein, wenn öffentliche Open-Source-Pakete verwendet werden oder die CI/CD-Konfiguration nicht ordnungsgemäß eingerichtet ist. Paketmanager wurden aus Gründen der Benutzerfreundlichkeit entwickelt. Diese Benutzerfreundlichkeit hat jedoch ihren Preis. Diese Paketmanager geben höheren Versionsnummern Vorrang vor der Herkunft des Quellcodes. Dann nimmt die Sache immer mehr Fahrt auf.

 

Was ist ein Dependency-Confusion-Angriff?

 

Angriffe durch Abhängigkeitsverwirrung zielen auf die Art und Weise ab, wie moderne Paketmanager Abhängigkeiten über mehrere Quellen hinweg auflösen. In Umgebungen, in denen sowohl private als auch öffentliche Registries verwendet werden, kann dieser Auflösungsprozess unerwartete Risiken mit sich bringen.

Was wie eine routinemäßige Installation von Abhängigkeiten aussieht, kann stattdessen zu einem Einfallstor für Schadcode werden – insbesondere wenn interne Pakete nicht ordnungsgemäß isoliert oder in ihrem Geltungsbereich eingeschränkt sind.

Wie Abhängigkeitsverwirrung funktioniert

 

Ein „Dependency Confusion“-Angriff (oder „Namespace Confusion“) nutzt eine Schwachstelle aus, die darin besteht, wie Paketmanager Abhängigkeiten über mehrere Registries hinweg auflösen. Er tritt auf, wenn ein Build-System so konfiguriert ist, dass es sowohl aus einer privaten (internen) Registry als auch aus einer öffentlichen Registry (wie npmjs.com) Daten abzurufen.

Wenn ein Angreifer den Namen eines privaten Pakets ohne Gültigkeitsbereich ermittelt und ein bösartiges Paket mit genau demselben Namen und einer höheren Versionsnummer in der öffentlichen Registrierungsdatenbank veröffentlicht, erkennt der Paketmanager die öffentliche, bösartige Version als „beste Übereinstimmung“ und fügt sie stillschweigend in die Lieferkette ein. Dies geschieht, weil Paketmanager bei übereinstimmenden Namen höheren Versionen Vorrang einräumen.

In der Praxis wählen Paketmanager die höchste Version aus, die die Semver Bereich erfüllt, wie oben beschrieben. Wenn Ihre package.json nach ^1.2.0 von internal-tool, und der Angreifer veröffentlicht v99.0.0 auf npmjs.com veröffentlicht, geht der Manager davon aus, dass es sich bei der öffentlichen Version um ein legitimes Update handelt, und lädt sie herunter.

Ein weiteres häufiges Szenario tritt auf, wenn eine Organisation keine bereichsbezogenen Pakete verwendet. Das Paket wurde in der privaten Registry als auth-package , aber es gibt auch ein Paket mit demselben Namen in der öffentlichen Registry. Die Registry ruft das Paket mit der höchsten Versionsnummer ab, sofern in der .npmrc angegeben ist.

Aufschlüsselung der transitiven Abhängigkeiten

 

Eine transitive Abhängigkeit ist ein Paket, das nicht absichtlich von Ihnen, dem Entwickler, installiert wurde, sondern bei der Installation einer direkten Abhängigkeit für ein Projekt mitinstalliert wird. Transitive Abhängigkeiten können sich mehrere Ebenen tief im Abhängigkeitsbaum verbergen, was es schwierig macht, den Ursprung von Sicherheitslücken genau zu lokalisieren.

„Die meisten Vorfälle im Bereich der Cybersicherheit standen im Zusammenhang mit nicht installierten Patches. 60,4 % der Vorfälle ereigneten sich, obwohl ein Patch verfügbar war, aber nicht installiert wurde.“

 

Um Sicherheitslücken durch transitive Abhängigkeiten in der Software-Lieferkette zu bekämpfen, ist es entscheidend, stets einen Schritt voraus zu sein und Patches rechtzeitig zu installieren. Nachstehend finden Sie ein Beispiel dafür, wie eine transitive Abhängigkeit aussieht.

rxjs ist eine direkte Abhängigkeit von Angular v20, aber wenn man sich das Verzeichnis node_modules und dort die Datei rxjs -Ordner finden, sehen Sie im package.json die tslib . Dieses Paket wurde nicht von Ihnen installiert, sondern kam als Teil des rxjs Paket im Angular-v20-Projekt mitgeliefert.

Anatomie eines Dependency-Confusion-Angriffs

 

Nehmen wir eine einfache Benutzeroberflächenkomponente, die Sie in einem Projekt einbinden möchten: eine einfache Schaltfläche. Diese Schaltfläche stammt direkt aus dem Designsystem Ihrer Organisation und befindet sich in einer Komponentenbibliothek.

Viel mehr steckt nicht dahinter. Ein Hintergrund, eine Schriftart mit Text und abgerundete Ecken. Dieser Button entspricht genau dem, was im Designsystem vorgesehen ist. Der Code wurde mit React erstellt und sieht so aus:

 

export const DemoButton = () => {

  return (

    <button style={{ backgroundColor: 'blue', color: 'white' }}>

      Secure Scoped Action

    </button>

  );

};

 

Wir installieren es über npm, binden es in unser Projekt ein, und schon ist es fertig. Ein funktionierender Button in unserer Benutzeroberfläche. Andererseits gibt es aber noch einen weiteren ausgefallener Button , und dieser Button ist entweder nicht in der privaten Registry eingeschränkt oder er ist zwar eingeschränkt, aber ein Entwickler installiert die öffentlich zugängliche Version. Die öffentlich zugängliche Version ist die bösartige, die Warnmeldungen auf der Startseite auslöst, Anmeldedaten im Hintergrund abfängt oder die Farben der Website umkehrt, entweder sofort oder nach einer bestimmten Zeit.

Der Code für diese Schaltfläche sieht so aus – vielleicht hast du ihn dir noch nicht angesehen:



import React, { useEffect } from 'react';



export const DemoButton = () => {

  useEffect(() => {

    document.body.style.filter = 'invert(100%)';

    alert("Hacked via Unscoped Dependency!");

  }, []);




  return <button>Click for Update</button>;

};

 

Es ist gut möglich, dass dieser Button nicht als direkte Abhängigkeit mitgeliefert wird. Im Beispielcode zeige ich ihn als direkte Abhängigkeit, da ich noch kein vollständiges Designsystem mit mehreren Komponenten aufgebaut habe. Wenn Sie eine nicht verifizierte UI-Bibliothek oder ein Paket installieren, das als Abhängigkeit für Ihr Designsystem dient, könnte ein bösartiger Button transitiv eingeschleust werden.

Unabhängig davon, ob sie direkt oder transitiv eingebunden werden, werden diese Abhängigkeiten Teil der Vertrauensgrenze Ihrer Anwendung – und stellen eine potenzielle Angriffsfläche dar, wenn sie nicht überprüft werden.

Angriffe vor und nach der Installation

 

Angreifer nutzen vor und Postinstall-Skripte Skripte, um bösartige Payloads auszuführen, noch bevor ein Entwickler überhaupt Zeit hat, den Code auszuführen. Die Art und Weise, wie ein Preinstall-Skript Skript funktioniert: Bevor Paketdateien in Ihren Ordner kopiert werden, führt das Skript möglicherweise Umgebungsprüfungen durch, um zu entscheiden, ob böswilliges Verhalten ausgeführt werden soll. Erkennt das Skript eine gehärtete oder überwachte Umgebung, meldet es sich unbemerkt bei seinem Server und bleibt inaktiv, um einer Entdeckung zu entgehen.

Die postinstall wartet darauf, dass die Tür entriegelt wird, und dann kann eine ganze Reihe von Dingen passieren. Ein postinstall Skript kann Geheimnisse stehlen oder, um es mit den Worten von E.T. zu sagen, „nach Hause telefonieren“ und dem Server mitteilen, dass die Tür weit offen steht und jeder hereinkommen kann. Man kann dies mit der Vampir-Sagenwelt vergleichen. Sobald man einen Vampir hereinlässt, ist die Jagdsaison eröffnet.

Sobald sich das Skript in Ihrem node_modulesbefindet, ist es zu spät – es wird sofort ausgeführt. Das Skript führt einen Befehl wie curl oder wget , um deine .env Dateien, SSH-Schlüssel oder AWS-Token an die Website des Angreifers zu senden. Sobald dieser über diese Zugangsdaten verfügt, können Sie nicht viel tun, außer Ihre Schlüssel/Token zu löschen und neue zu generieren.

Behebung von Abhängigkeitskonflikten

 

Es gibt verschiedene Möglichkeiten, wie wir diesen Problemen zuvorkommen und zu einem sicheren, auf dem neuesten Stand befindlichen Projekt gelangen können. 

Pakete mit Gültigkeitsbereich

Der einfachste Weg, um Angriffe durch Abhängigkeitsverwirrung zu vermeiden, besteht darin, Ihre Organisation beim Paketmanager zu registrieren und scoped-Pakete zu verwenden, @myorg/mypackage. Dadurch erhalten Sie ein sicheres, privates Paket, das innerhalb Ihrer eigenen Projekte in der gesamten Organisation verwendet werden kann.

Richtig .npmrc Konfigurationen

Beim Erstellen Ihrer .npmrc Datei erstellen, achten Sie darauf, bestimmte Bereiche strikt privaten Registries zuzuordnen. Durch diese strikte Zuordnung wird verhindert, dass sie in die öffentliche Registry „durchsickern“. Ein Beispiel für eine .npmrc , die dafür eingerichtet ist, sieht wie folgt aus und stellt die effektivste Methode dar, um Probleme in Ihrem Projekt zu bekämpfen:

 

# Standard-Repository für öffentliche Pakete festlegen

registry=https://registry.npmjs.org/




# Alle Pakete im @org-Bereich NUR über die private Registry auflösen

@org:registry=https://npm.pkg.github.com/

always-auth=true

Verwendung von –ignore-scripts

Another clever way to get away from the preinstall and postinstall scripts is to use –ignore-scripts when installing packages. Using that flag looks like this: npm install <new-package> –ignore-scripts. This isn’t just something that is used once; you want to bake this into your automation and workflows as well.

Integrität der Sperrdatei

Deine package-lock.json oder yarn.lock macht mehr als nur Versionen festzulegen; es speichert einen Hash, einen kryptografischen Hash. Wenn sich der Hash ändert und der Build fehlschlägt, weist dies darauf hin, dass ein Angreifer das Paket in der Registry ausgetauscht hat. Mit npm ci wird die Lock-Datei erzwungen. Mit npm installkann dieser Schutz umgangen werden.

Den Stapel sichern

Berücksichtigen Sie all diese Punkte und halten Sie sich unbedingt an eine strenge Sicherheitscheckliste. Diese Punkte sind nur ein Teil davon.

 

  1. Verwenden Sie scoped-Pakete und stellen Sie sicher, dass Sie Ihre Organisation in der Registry registrieren
  2. Konfigurieren Sie Ihre .npmrc so, dass Ihre Pakete ausschließlich der privaten Registry zugeordnet werden
  3. Verwenden Sie –ignore-scripts in Ihren CI/CD-Pipelines, um preinstall und postinstall Skripte standardmäßig zu deaktivieren

 

Die Sicherheit der Lieferkette ist keine Aufgabe, die man einmal einrichtet und dann vergessen kann, wie bei einem Ronco-Grillofen; sie erfordert ständige Wachsamkeit, während sich Ihr Projekt weiterentwickelt. Es ist etwas, das von Anfang an und auch in Zukunft, während sich das Projekt weiterentwickelt, berücksichtigt werden muss.

Sichern Sie Ihre Registries, überprüfen Sie Ihre Scopes und behalten Sie im Blick, was tief in Ihrem Abhängigkeitsbaum vor sich geht. Die größten Risiken sind nicht immer sichtbar – aber oft befinden sie sich bereits in Ihrem Stack. In Anlehnung an die Metapher vom Vampir, der nicht ins Haus eingeladen wurde, möchte ich Ihnen dieses Zitat aus „The Lost Boys“ mit auf den Weg geben: „Eine Sache am Leben in Santa Carla konnte ich nie ertragen: all die verdammten Vampire.“ Santa Carla ist die Software, und die Vampire sind die Sicherheitslücken. Seien Sie immer einen Schritt voraus und lassen Sie sie nicht herein.

 

Zusammenfassung
Dependency-Confusion-Angriff – So funktioniert er und wie man ihn verhindert
Artikel Name
Dependency-Confusion-Angriff – So funktioniert er und wie man ihn verhindert
Beschreibung
Erfahren Sie, wie Dependency-Confusion-Angriffe funktionieren, wie sie npm und transitive Abhängigkeiten ausnutzen und wie Sie Ihre Software-Lieferkette absichern können.
Autor
Name des Herausgebers
TuxCare
Logo des Herausgebers

Schließen Sie sich 4.500+ Linux- und Open-Source-Experten an!

2x im Monat. Kein Spam.

Inhaltsübersicht
Holen Sie sich die Open-Source-Sicherheitslösungen, die Sie brauchen

Schließen Sie sich 4.500+ Linux- und Open-Source-Experten an!

2x im Monat. Kein Spam.