# Dependency Confusion {{#include ../banners/hacktricks-training.md}} ## 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 traži u javnim registracijama i pronalazi paket napadača. - Preferencija verzije među više registracija: 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 registracija 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 odlazni saobraćaj 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/ verzije paketa 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” među registracijama). - Pin and lock: - Koristite lockfiles koji beleže URL-ove rešene registracije (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, a 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 hash pinovanje. 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 ``` ``` ### Java (Maven/Gradle) Maven settings.xml (ogledalo sve na interno; zabraniti ad-hoc repozitorijume u POM-ima putem Enforcer): ``` internal-mirror * https://maven.corp.example/repository/group ``` Dodajte Enforcer da zabranite repozitorijume deklarisane u POM-ovima i primorate korišćenje vašeg ogledala: ``` org.apache.maven.plugins maven-enforcer-plugin 3.6.1 enforce-no-repositories enforce ``` 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 izgradnje; 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 unutrašnji 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 unutrašnja 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 da je manipulacija lakše uočljiva nizvodno. ## Reference - [https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610) - [https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d](https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d) - [https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping](https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping) - [https://yarnpkg.com/configuration/yarnrc/](https://yarnpkg.com/configuration/yarnrc/) {{#include ../banners/hacktricks-training.md}}