Dependency Confusion
Reading time: 9 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Grundinformationen
Dependency Confusion (auch bekannt als Substitution-Angriffe) tritt auf, wenn ein Paketmanager einen Abhängigkeitsnamen aus einem unbeabsichtigten, weniger vertrauenswürdigen Registry/Quelle (in der Regel einem öffentlichen Registry) anstelle des beabsichtigten privaten/internen auflöst. Dies führt typischerweise zur Installation eines von einem Angreifer kontrollierten Pakets.
Häufige Ursachen:
- Typosquatting/Rechtschreibfehler: Importieren von
reqests
anstelle vonrequests
(wird aus dem öffentlichen Registry aufgelöst). - Nicht vorhandenes/verlassenes internes Paket: Importieren von
company-logging
, das intern nicht mehr existiert, sodass der Resolver in öffentlichen Registries nachschaut und ein Paket eines Angreifers findet. - Versionspräferenz über mehrere Registries: Importieren eines internen
company-requests
, während der Resolver auch öffentliche Registries abfragen darf und die „beste“/neuere Version bevorzugt, die öffentlich von einem Angreifer veröffentlicht wurde.
Schlüsselidee: Wenn der Resolver mehrere Registries für denselben Paketnamen sehen kann und berechtigt ist, den „besten“ Kandidaten global auszuwählen, sind Sie anfällig, es sei denn, Sie schränken die Auflösung ein.
Ausnutzung
warning
In allen Fällen muss der Angreifer nur ein bösartiges Paket mit demselben Namen wie die Abhängigkeit veröffentlichen, die Ihr Build aus einem öffentlichen Registry auflöst. Installationszeit-Hooks (z. B. npm-Skripte) oder Importzeit-Codepfade bieten oft die Möglichkeit zur Codeausführung.
Falsch geschrieben & Nicht vorhanden
Wenn Ihr Projekt auf eine Bibliothek verweist, die im privaten Registry nicht verfügbar ist, und Ihre Tools auf ein öffentliches Registry zurückgreifen, kann ein Angreifer ein bösartiges Paket mit diesem Namen im öffentlichen Registry bereitstellen. Ihre Runner/CI/Entwicklungsmaschinen werden es abrufen und ausführen.
Unbestimmte Version / „Beste-Version“-Auswahl über Indizes
Entwickler lassen häufig Versionen ungenau oder erlauben weite Bereiche. Wenn ein Resolver sowohl mit internen als auch mit öffentlichen Indizes konfiguriert ist, kann er die neueste Version unabhängig von der Quelle auswählen. Für interne Namen wie requests-company
, wenn der interne Index 1.0.1
hat, aber ein Angreifer 1.0.2
im öffentlichen Registry veröffentlicht und Ihr Resolver beide berücksichtigt, kann das öffentliche Paket gewinnen.
AWS Fix
Diese Schwachstelle wurde in AWS CodeArtifact gefunden (lesen Sie die Einzelheiten in diesem Blogbeitrag). AWS hat Kontrollen hinzugefügt, um Abhängigkeiten/Feeds als intern oder extern zu kennzeichnen, sodass der Client keine „internen“ Namen aus upstream öffentlichen Registries abruft.
Finden von Verwundbaren Bibliotheken
Im ursprünglichen Beitrag über Dependency Confusion suchte der Autor nach Tausenden von exponierten Manifests (z. B. package.json
, requirements.txt
, Lockfiles), um interne Paketnamen abzuleiten und dann höherversionierte Pakete in öffentlichen Registries zu veröffentlichen.
Praktisches Angreifer-Playbook (für rote Teams in autorisierten Tests)
- Namen auflisten:
- Grep-Repos und CI-Konfigurationen nach Manifest-/Lock-Dateien und internen Namensräumen durchsuchen.
- Nach organisationsspezifischen Präfixen suchen (z. B.
@company/*
,company-*
, interne groupIds, NuGet-ID-Muster, private Modulpfade für Go usw.). - Verfügbarkeit in öffentlichen Registries überprüfen:
- Wenn der Name öffentlich nicht registriert ist, registrieren Sie ihn; wenn er existiert, versuchen Sie, Subabhängigkeits-Hijacking durch gezielte interne transitive Namen durchzuführen.
- Mit Priorität veröffentlichen:
- Wählen Sie eine Semver, die „gewinnt“ (z. B. eine sehr hohe Version) oder den Regeln des Resolvers entspricht.
- Minimale Ausführung zur Installationszeit einfügen, wo anwendbar (z. B. npm
preinstall
/install
/postinstall
-Skripte). Für Python bevorzugen Sie Ausführungspfade zur Importzeit, da Wheels typischerweise keinen beliebigen Code bei der Installation ausführen. - Exfil-Kontrolle:
- Stellen Sie sicher, dass ausgehende Verbindungen von CI zu Ihrem kontrollierten Endpunkt erlaubt sind; andernfalls verwenden Sie DNS-Abfragen oder Fehlermeldungen als Seitenkanal, um die Codeausführung nachzuweisen.
caution
Holen Sie sich immer eine schriftliche Genehmigung, verwenden Sie eindeutige Paketnamen/-versionen für das Engagement und veröffentlichen Sie sofort oder koordinieren Sie die Bereinigung, wenn die Tests abgeschlossen sind.
Verteidiger-Playbook (was tatsächlich Verwirrung verhindert)
Hochrangige Strategien, die in verschiedenen Ökosystemen funktionieren:
- Verwenden Sie eindeutige interne Namensräume und binden Sie sie an ein einzelnes Registry.
- Vermeiden Sie es, Vertrauensstufen zur Auflösungszeit zu mischen. Bevorzugen Sie ein einzelnes internes Registry, das genehmigte öffentliche Pakete proxy, anstatt Paketmanagern sowohl interne als auch öffentliche Endpunkte zu geben.
- Für Manager, die es unterstützen, Pakete bestimmten Quellen zuzuordnen (keine globale „beste Version“ über Registries).
- Festlegen und Sperren:
- Verwenden Sie Lockfiles, die die aufgelösten Registry-URLs aufzeichnen (npm/yarn/pnpm) oder verwenden Sie Hash-/Attestierungs-Pinning (pip
--require-hashes
, Gradle-Abhängigkeitsüberprüfung). - Blockieren Sie öffentliche Rückfälle für interne Namen auf der Registry-/Netzwerkschicht.
- Reservieren Sie Ihre internen Namen in öffentlichen Registries, wenn möglich, um zukünftiges Squatting zu verhindern.
Ökosystemnotizen und sichere Konfigurationssnippets
Im Folgenden finden Sie pragmatische, minimale Konfigurationen zur Reduzierung oder Beseitigung von Dependency Confusion. Bevorzugen Sie es, diese in CI- und Entwicklerumgebungen durchzusetzen.
JavaScript/TypeScript (npm, Yarn, pnpm)
- Verwenden Sie Scoped-Pakete für gesamten internen Code und binden Sie den Scope an Ihr privates Registry.
- Halten Sie Installationen in CI unveränderlich (npm Lockfile,
yarn install --immutable
).
.npmrc (Projektebene)
# Bind internal scope to private registry; do not allow public fallback for @company/*
@company:registry=https://registry.corp.example/npm/
# Always authenticate to the private registry
//registry.corp.example/npm/:_authToken=${NPM_TOKEN}
strict-ssl=true
package.json (für internes Paket)
{
"name": "@company/api-client",
"version": "1.2.3",
"private": false,
"publishConfig": {
"registry": "https://registry.corp.example/npm/",
"access": "restricted"
}
}
Yarn Berry (.yarnrc.yml)
npmScopes:
company:
npmRegistryServer: "https://registry.corp.example/npm/"
npmAlwaysAuth: true
# CI should fail if lockfile would change
enableImmutableInstalls: true
Betriebliche Tipps:
- Veröffentlichen Sie interne Pakete nur innerhalb des
@company
-Scopes. - Für Drittanbieter-Pakete erlauben Sie das öffentliche Registry über Ihren privaten Proxy/Spiegel, nicht direkt von Clients.
- Erwägen Sie, die Herkunft von npm-Paketen für öffentliche Pakete, die Sie veröffentlichen, zu aktivieren, um die Rückverfolgbarkeit zu erhöhen (verhindert nicht von sich aus Verwirrung).
Python (pip / Poetry)
Kernregel: Verwenden Sie --extra-index-url
nicht, um Vertrauensstufen zu mischen. Entweder:
- Stellen Sie einen einzigen internen Index bereit, der genehmigte PyPI-Pakete proxy und zwischenspeichert, oder
- Verwenden Sie explizite Indexauswahl und Hash-Pinning.
pip.conf
[global]
index-url = https://pypi.corp.example/simple
# Disallow source distributions when possible
only-binary = :all:
# Lock with hashes generated via pip-tools
require-hashes = true
Generiere gehashte Anforderungen mit pip-tools:
# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt
Wenn Sie auf das öffentliche PyPI zugreifen müssen, tun Sie dies über Ihren internen Proxy und führen Sie dort eine explizite Erlaubenliste. Vermeiden Sie --extra-index-url
in CI.
.NET (NuGet)
Verwenden Sie Package Source Mapping, um Paket-ID-Muster mit expliziten Quellen zu verknüpfen und die Auflösung von unerwarteten Feeds zu verhindern.
nuget.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="corp" value="https://nuget.corp.example/v3/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="corp">
<package pattern="Company.*" />
<package pattern="Internal.Utilities" />
</packageSource>
</packageSourceMapping>
</configuration>
Java (Maven/Gradle)
Maven settings.xml (alle auf intern spiegeln; ad-hoc Repos in POMs über Enforcer nicht zulassen):
<settings>
<mirrors>
<mirror>
<id>internal-mirror</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.corp.example/repository/group</url>
</mirror>
</mirrors>
</settings>
Fügen Sie Enforcer hinzu, um in POMs deklarierte Repositories zu verbannen und die Verwendung Ihres Mirrors zu erzwingen:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>enforce-no-repositories</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<requireNoRepositories />
</rules>
</configuration>
</execution>
</executions>
</plugin>
Gradle: Abhängigkeiten zentralisieren und sperren.
- Erzwingen Sie Repositories nur in
settings.gradle(.kts)
:
dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
maven { url = uri("https://maven.corp.example/repository/group") }
}
}
- Aktivieren Sie die Abhängigkeitsüberprüfung (Prüfziffern/Signaturen) und committen Sie
gradle/verification-metadata.xml
.
Go-Module
Konfigurieren Sie private Module, damit der öffentliche Proxy und die Prüfzifferndatenbank nicht für sie verwendet werden.
# Use corporate proxy first, then public proxy as fallback
export GOPROXY=https://goproxy.corp.example,https://proxy.golang.org
# Mark private paths to skip proxy and checksum db
export GOPRIVATE=*.corp.example.com,github.com/your-org/*
export GONOSUMDB=*.corp.example.com,github.com/your-org/*
Rust (Cargo)
Ersetzen Sie crates.io durch einen genehmigten internen Mirror oder ein Vendor-Verzeichnis für Builds; erlauben Sie keinen beliebigen öffentlichen Fallback.
.cargo/config.toml
[source.crates-io]
replace-with = "corp-mirror"
[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"
Für die Veröffentlichung seien Sie explizit mit --registry
und halten Sie die Anmeldeinformationen auf das Ziel-Registry beschränkt.
Ruby (Bundler)
Verwenden Sie Quellblöcke und deaktivieren Sie Multisource-Gemfiles, damit Gems nur aus dem beabsichtigten Repository stammen.
Gemfile
source "https://gems.corp.example"
source "https://rubygems.org" do
gem "rails"
gem "pg"
end
source "https://gems.corp.example" do
gem "company-logging"
end
Auf Konfigurationsebene durchsetzen:
bundle config set disable_multisource true
CI/CD und Registry-Kontrollen, die helfen
- Private Registry als einziger Zugang:
- Verwenden Sie Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts als den einzigen Endpunkt, den Entwickler/CI erreichen können.
- Implementieren Sie Block-/Erlauben-Regeln, damit interne Namespaces niemals von öffentlichen Quellen aufgelöst werden.
- Lockfiles sind in CI unveränderlich:
- npm: commit
package-lock.json
, verwenden Sienpm ci
. - Yarn: commit
yarn.lock
, verwenden Sieyarn install --immutable
. - Python: commit gehashtes
requirements.txt
, erzwingen Sie--require-hashes
. - Gradle: commit
verification-metadata.xml
und schlagen Sie bei unbekannten Artefakten fehl. - Ausgehende Egress-Kontrolle: blockieren Sie den direkten Zugriff von CI auf öffentliche Registries, außer über den genehmigten Proxy.
- Namensreservierung: registrieren Sie Ihre internen Namen/Namensräume in öffentlichen Registries, wo unterstützt.
- Paketherkunft / Bestätigungen: aktivieren Sie bei der Veröffentlichung öffentlicher Pakete Herkunft/Bestätigungen, um Manipulationen downstream leichter erkennbar zu machen.
Referenzen
- https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610
- https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d
- https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping
- https://yarnpkg.com/configuration/yarnrc/
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.