Dependency Confusion

Reading time: 9 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Basic Information

Dependency Confusion (poznat i kao napadi zamene) se dešava kada menadžer paketa rešava ime zavisnosti iz nepredviđene, manje pouzdane registracije/izvora (obično javne registracije) umesto iz predviđene privatne/interni. Ovo obično dovodi do instalacije paketa koji kontroliše napadač.

Uobičajeni uzroci:

  • Typosquatting/pravopisne greške: Uvoz reqests umesto requests (rešava iz javne registracije).
  • Nepostojeći/napušteni interni paket: Uvoz company-logging koji više ne postoji interno, pa resolver gleda u javne registracije i pronalazi paket napadača.
  • Preferencija verzije preko više registrija: Uvoz internog company-requests dok resolver može da pretražuje javne registracije i preferira “najbolju”/noviju verziju koju je objavio napadač.

Ključna ideja: Ako resolver može da vidi više registrija za isto ime paketa i dozvoljeno mu je da izabere “najboljeg” kandidata globalno, ranjivi ste osim ako ne ograničite rešavanje.

Exploitation

warning

U svim slučajevima, napadaču je potrebno samo da objavi zlonameran paket sa istim imenom kao zavisnost koju vaša izgradnja rešava iz javne registracije. Hooks u vreme instalacije (npr. npm skripte) ili putanje koda u vreme uvoza često omogućavaju izvršavanje koda.

Misspelled & Inexistent

Ako vaš projekat referencira biblioteku koja nije dostupna u privatnoj registraciji, i vaši alati se vraćaju na javnu registraciju, napadač može da postavi zlonameran paket sa tim imenom u javnoj registraciji. Vaši runneri/CI/dev mašine će ga preuzeti i izvršiti.

Unspecified Version / “Best-version” selection across indexes

Programeri često ostavljaju verzije neodređene ili dozvoljavaju široke opsege. Kada je resolver konfiguran sa internim i javnim indeksima, može izabrati najnoviju verziju bez obzira na izvor. Za interna imena kao što je requests-company, ako interni indeks ima 1.0.1 ali napadač objavi 1.0.2 u javnoj registraciji i vaš resolver uzima u obzir oboje, javni paket može pobediti.

AWS Fix

Ova ranjivost je pronađena u AWS CodeArtifact (pročitajte detalje u ovom blog postu). AWS je dodao kontrole da označi zavisnosti/izvore kao interne ili eksterne tako da klijent neće preuzimati “interno” imena iz uzvodnih javnih registracija.

Finding Vulnerable Libraries

U originalnom postu o konfuziji zavisnosti, autor je tražio hiljade izloženih manifestacija (npr. package.json, requirements.txt, lockfiles) da bi inferirao interna imena paketa i zatim objavio pakete sa višim verzijama u javnim registracijama.

Practical Attacker Playbook (for red teams in authorized tests)

  • Enumerate names:
  • Grep repos and CI configs for manifest/lock files and internal namespaces.
  • Look for organization-specific prefixes (npr. @company/*, company-*, interni groupIds, NuGet ID obrasci, privatne putanje modula za Go, itd.).
  • Check public registries for availability:
  • Ako ime nije registrovano javno, registrujte ga; ako postoji, pokušajte sa otmicom subzavisnosti ciljanjem internih tranzitivnih imena.
  • Publish with precedence:
  • Izaberite semver koji “pobeđuje” (npr. veoma visoka verzija) ili se poklapa sa pravilima resolvera.
  • Uključite minimalno izvršavanje u vreme instalacije gde je primenljivo (npr. npm preinstall/install/postinstall skripte). Za Python, preferirajte putanje izvršavanja u vreme uvoza, jer točkići obično ne izvršavaju proizvoljan kod prilikom instalacije.
  • Exfil control:
  • Osigurajte da je izlaz dozvoljen iz CI ka vašem kontrolisanom kraju; inače koristite DNS upite ili poruke o grešci kao bočni kanal za dokazivanje izvršavanja koda.

caution

Uvek dobijte pisanu autorizaciju, koristite jedinstvena imena paketa/verzije za angažovanje, i odmah povucite ili koordinirajte čišćenje kada testiranje završi.

Defender Playbook (what actually prevents confusion)

Visok nivo strategija koje funkcionišu širom ekosistema:

  • Koristite jedinstvene interne prostore imena i povežite ih sa jednom registracijom.
  • Izbegavajte mešanje nivoa poverenja u vreme rešavanja. Preferirajte jednu internu registraciju koja proksira odobrene javne pakete umesto da dajete menadžerima paketa i interne i javne krajnje tačke.
  • Za menadžere koji to podržavaju, mapirajte pakete na specifične izvore (bez globalne “najbolje verzije” preko registrija).
  • Pin and lock:
  • Koristite lockfiles koji beleže rešene URL-ove registracija (npm/yarn/pnpm) ili koristite hash/attestation pinning (pip --require-hashes, Gradle verifikacija zavisnosti).
  • Blokirajte javno vraćanje za interna imena na registracionom/mrežnom sloju.
  • Rezervišite svoja interna imena u javnim registracijama kada je to moguće da biste sprečili buduće squat.

Ecosystem Notes and Secure Config Snippets

Ispod su pragmatične, minimalne konfiguracije za smanjenje ili eliminisanje konfuzije zavisnosti. Preferirajte primenu ovih u CI i razvojnim okruženjima.

JavaScript/TypeScript (npm, Yarn, pnpm)

  • Koristite skopirane pakete za sav interni kod i pinujte sklop na vašu privatnu registraciju.
  • Održavajte instalacije nepromenljive u CI (npm lockfile, yarn install --immutable).

.npmrc (project-level)

# 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 (za internu 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

Operational tips:

  • Objavite samo interne pakete unutar @company opsega.
  • Za pakete trećih strana, dozvolite javni registar putem vašeg privatnog proksija/ogledala, ne direktno od klijenata.
  • Razmotrite omogućavanje npm paketa porekla za javne pakete koje objavljujete kako biste povećali traganje (to samo po sebi ne sprečava konfuziju).

Python (pip / Poetry)

Osnovno pravilo: Ne koristite --extra-index-url za mešanje nivoa poverenja. Ili:

  • Izložite jedan interni indeks koji proksira i kešira odobrene PyPI pakete, ili
  • Koristite eksplicitnu selekciju indeksa i pinovanje heša.

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

Generišite heširane zahteve pomoću pip-tools:

# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt

Ako morate da pristupite javnom PyPI, učinite to putem vašeg internog proksija i održavajte eksplicitnu dozvoljenu listu tamo. Izbegavajte --extra-index-url u CI.

.NET (NuGet)

Koristite Mapiranje Izvora Paketa da povežete obrasce ID-a paketa sa eksplicitnim izvorima i sprečite rešavanje iz neočekivanih izvora.

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 (ogledalo sve na interno; zabraniti ad-hoc repozitorijume u POM-ima putem Enforcer):

<settings>
<mirrors>
<mirror>
<id>internal-mirror</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.corp.example/repository/group</url>
</mirror>
</mirrors>
</settings>

Dodajte Enforcer da zabranite repozitorijume deklarisane u POM-ovima i primorate korišćenje vašeg ogledala:

<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: Centralizujte i zaključajte zavisnosti.

  • Primorajte repozitorijume u settings.gradle(.kts) samo:
dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
maven { url = uri("https://maven.corp.example/repository/group") }
}
}
  • Omogućite verifikaciju zavisnosti (provere kontrolnih suma/potpisivanja) i sačuvajte gradle/verification-metadata.xml.

Go Moduli

Konfigurišite privatne module tako da se javni proxy i baza podataka kontrolnih suma ne koriste za njih.

# 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)

Zamenite crates.io sa odobrenim internim ogledalom ili direktorijumom dobavljača za gradnje; ne dozvolite proizvoljno javno vraćanje.

.cargo/config.toml

[source.crates-io]
replace-with = "corp-mirror"

[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"

Za objavljivanje, budite eksplicitni sa --registry i zadržite akreditive ograničene na ciljni registar.

Ruby (Bundler)

Koristite blokove izvora i onemogućite multisource Gemfile-ove tako da gemovi dolaze samo iz nameravane biblioteke.

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

Sprovodite na nivou konfiguracije:

bundle config set disable_multisource true

CI/CD i kontrole registra koje pomažu

  • Privatni registar kao jedini ulaz:
  • Koristite Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts kao jedinu tačku koju developeri/CI mogu da dostignu.
  • Implementirajte pravila blokiranja/dozvoljavanja tako da interni prostori imena nikada ne budu rešeni iz javnih izvora.
  • Lockfajlovi su nepromenljivi u CI:
  • npm: komitujte package-lock.json, koristite npm ci.
  • Yarn: komitujte yarn.lock, koristite yarn install --immutable.
  • Python: komitujte heširani requirements.txt, primenite --require-hashes.
  • Gradle: komitujte verification-metadata.xml i ne uspevajte na nepoznatim artefaktima.
  • Kontrola izlaznog saobraćaja: blokirajte direktan pristup iz CI ka javnim registrima osim putem odobrenog proksija.
  • Rezervacija imena: unapred registrujte svoja interna imena/prostore imena u javnim registrima gde je to podržano.
  • Poreklo paketa / potvrde: kada objavljujete javne pakete, omogućite poreklo/potvrde kako biste učinili prepravke uočljivijim nizvodno.

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks