12 KiB
Afhanklikheid Verwarring
{{#include ../banners/hacktricks-training.md}}
Basiese Inligting
Afhanklikheid Verwarring (ook bekend as vervangingsaanvalle) gebeur wanneer 'n pakketbestuurder 'n afhanklikheidsnaam van 'n onbedoelde, minder betroubare registrasie/bron (gewoonlik 'n openbare registrasie) oplos in plaas van die bedoelde privaat/interne een. Dit lei tipies tot die installasie van 'n pakket wat deur 'n aanvaller beheer word.
Gewone wortel oorsake:
- Spelfoute: Invoer van
reqests
in plaas vanrequests
(los op vanaf openbare registrasie). - Nie-bestaande/abandonne interne pakket: Invoer van
company-logging
wat nie meer intern bestaan nie, so die oplosser kyk in openbare registrasies en vind 'n aanvaller se pakket. - Weergawe voorkeur oor verskeie registrasies: Invoer van 'n interne
company-requests
terwyl die oplosser toegelaat word om ook openbare registrasies te ondervra en die “beste”/nuwer weergawe wat publiek deur 'n aanvaller gepubliseer is, verkies.
Belangrike idee: As die oplosser verskeie registrasies vir dieselfde pakketnaam kan sien en toegelaat word om die “beste” kandidaat globaal te kies, is jy kwesbaar tensy jy oplos beperk.
Exploitatie
Warning
In alle gevalle hoef die aanvaller slegs 'n kwaadwillige pakket met dieselfde naam as die afhanklikheid wat jou bou vanaf 'n openbare registrasie oplos, te publiseer. Installasie-tyd haakies (bv. npm skripte) of invoer-tyd kodepade gee dikwels kode-uitvoering.
Spelfoute & Nie-bestaande
As jou projek 'n biblioteek verwys wat nie in die privaat registrasie beskikbaar is nie, en jou gereedskap terugval op 'n openbare registrasie, kan 'n aanvaller 'n kwaadwillige pakket met daardie naam in die openbare registrasie plaas. Jou lopers/CI/dev masjiene sal dit aflaai en uitvoer.
Ongespesifiseerde Weergawe / “Beste-weergawe” seleksie oor indekse
Ontwikkelaars laat dikwels weergawe onvas of laat wye reekse toe. Wanneer 'n oplosser geconfigureer is met beide interne en openbare indekse, kan dit die nuutste weergawe kies ongeag die bron. Vir interne name soos requests-company
, as die interne indeks 1.0.1
het maar 'n aanvaller 1.0.2
na die openbare registrasie publiseer en jou oplosser beide oorweeg, kan die openbare pakket wen.
AWS Oplossing
Hierdie kwesbaarheid is in AWS CodeArtifact gevind (lees die besonderhede in hierdie blogpos). AWS het beheermaatreëls bygevoeg om afhanklikhede/voedings as intern vs ekstern te merk sodat die kliënt nie “interne” name van opwaartse openbare registrasies sal aflaai nie.
Vind Kwesbare Biblioteke
In die oorspronklike pos oor afhanklikheid verwarring het die outeur na duisende blootgestelde manifes (bv. package.json
, requirements.txt
, slotlêers) gesoek om interne pakketname af te lei en toe hoër-weergawe pakkette na openbare registrasies gepubliseer.
Praktiese Aanvaller Speelboek (vir rooi span in gemagtigde toetse)
- Tel name op:
- Grep repos en CI konfigurasies vir manifest/slot lêers en interne namespaces.
- Soek na organisasie-spesifieke voorvoegsels (bv.
@company/*
,company-*
, interne groepIds, NuGet ID patrone, private module paden vir Go, ens.). - Kontroleer openbare registrasies vir beskikbaarheid:
- As die naam nie publiek geregistreer is nie, registreer dit; as dit bestaan, probeer subafhanklikheid kaap deur interne transitive name te teiken.
- Publiseer met prioriteit:
- Kies 'n semver wat “wen” (bv. 'n baie hoë weergawe) of wat ooreenstem met oplosser reëls.
- Sluit minimale installasie-tyd uitvoering in waar toepaslik (bv. npm
preinstall
/install
/postinstall
skripte). Vir Python, verkies invoer-tyd uitvoering paden, aangesien wiele tipies nie willekeurige kode op installasie uitvoer nie. - Exfil beheer:
- Verseker dat uitgaande verkeer toegelaat word van CI na jou beheerde eindpunt; anders gebruik DNS vrae of foutboodskappe as 'n sy-kanaal om kode-uitvoering te bewys.
Caution
Kry altyd skriftelike toestemming, gebruik unieke pakketname/weergawe vir die betrokkenheid, en onttrek of koördineer onmiddellik skoonmaak wanneer toetse eindig.
Verdediger Speelboek (wat werklik verwarring voorkom)
Hoofvlak strategieë wat oor ekosisteme werk:
- Gebruik unieke interne namespaces en bind hulle aan 'n enkele registrasie.
- Vermy om vertrouensvlakke te meng tydens die oplos. Verkies 'n enkele interne registrasie wat goedgekeurde openbare pakkette proxy in plaas van om pakketbestuurders beide interne en openbare eindpunte te gee.
- Vir bestuurders wat dit ondersteun, kaart pakkette na spesifieke bronne (geen globale “beste-weergawe” oor registrasies).
- Pin en sluit:
- Gebruik slotlêers wat die opgeloste registrasie-URL's opteken (npm/yarn/pnpm) of gebruik hash/attestering pinning (pip
--require-hashes
, Gradle afhanklikheid verifikasie). - Blokkeer openbare terugval vir interne name op die registrasie/netwerk laag.
- Reserveer jou interne name in openbare registrasies wanneer moontlik om toekomstige squat te voorkom.
Ekosisteem Aantekeninge en Veilige Konfig Snippets
Hieronder is pragmatiese, minimale konfigurasies om afhanklikheid verwarring te verminder of te elimineer. Verkies om dit in CI en ontwikkelaar omgewings af te dwing.
JavaScript/TypeScript (npm, Yarn, pnpm)
- Gebruik gescopeerde pakkette vir alle interne kode en pin die skoop na jou privaat registrasie.
- Hou installasies onveranderlik in CI (npm slotlêer,
yarn install --immutable
).
.npmrc (projekvlak)
# 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 (vir interne pakket)
{
"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:
- Publiseer slegs interne pakkette binne die
@company
omvang. - Vir derdeparty pakkette, laat publieke registrasie via jou private proxy/spieël, nie direk van kliënte nie.
- Oorweeg om npm-pakket oorsprong in te skakel vir publieke pakkette wat jy publiseer om die opspoorbaarheid te verhoog (dit voorkom nie self verwarring nie).
Python (pip / Poetry)
Kernreël: Moet nie --extra-index-url
gebruik om vertrouensvlakke te meng nie. Of:
- Stel 'n enkele interne indeks bloot wat goedgekeurde PyPI-pakkette proxy en kas, of
- Gebruik eksplisiete indekskeuse en 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
Genereer gehashde vereistes met pip-tools:
# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt
As jy openbare PyPI moet bereik, doen dit via jou interne proxy en hou 'n eksplisiete toelaatlys daar. Vermy --extra-index-url
in CI.
.NET (NuGet)
Gebruik Pakketbronkaart om pakket-ID patrone aan eksplisiete bronne te koppel en om resolusie van onverwagte voedings te voorkom.
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 (spieël alles na intern; verbied ad-hoc repos in POMs via Enforcer):
<settings>
<mirrors>
<mirror>
<id>internal-mirror</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.corp.example/repository/group</url>
</mirror>
</mirrors>
</settings>
Voeg Enforcer by om repositories wat in POMs verklaar is te verbied en die gebruik van jou spieël af te dwing:
<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: Sentriseer en sluit afhanklikhede.
- Handhaaf repositories in
settings.gradle(.kts)
slegs:
dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
maven { url = uri("https://maven.corp.example/repository/group") }
}
}
- Aktiveer afhanklikheidsverifikasie (kontrole som/handtekeninge) en verbind
gradle/verification-metadata.xml
.
Go Modules
Konfigureer private modules sodat die openbare proxy en kontrole som DB nie vir hulle gebruik word nie.
# 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)
Vervang crates.io met 'n goedgekeurde interne spieël of verkoper gids vir bou; moenie willekeurige openbare terugval toelaat nie.
.cargo/config.toml
[source.crates-io]
replace-with = "corp-mirror"
[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"
Vir publikasie, wees eksplisiet met --registry
en hou geloofsbriewe geskaald tot die teiken registrasie.
Ruby (Bundler)
Gebruik bronblokke en deaktiveer multisource Gemfiles sodat gems slegs van die bedoelde repository kom.
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
Handhaaf op konfigurasievlak:
bundle config set disable_multisource true
CI/CD en Registrasie Beheer Wat Help
- Privaat registrasie as 'n enkele toegangspunt:
- Gebruik Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts as die enigste eindpunt wat ontwikkelaars/CI kan bereik.
- Implementeer blok/laat toe reëls sodat interne namespaces nooit van opwaartse publieke bronne opgelos word nie.
- Lockfiles is onveranderlik in CI:
- npm: commit
package-lock.json
, gebruiknpm ci
. - Yarn: commit
yarn.lock
, gebruikyarn install --immutable
. - Python: commit gehashede
requirements.txt
, afdwing--require-hashes
. - Gradle: commit
verification-metadata.xml
en faal op onbekende artefakte. - Uitgaande egress beheer: blok direkte toegang van CI na publieke registrasies behalwe via die goedgekeurde proxy.
- Naam reservasie: registreer jou interne name/namespaces vooraf in publieke registrasies waar ondersteun.
- Pakket oorsprong / bevestigings: wanneer jy publieke pakkette publiseer, stel oorsprong/bevestigings in om vervalsing meer opspoorbaar te maak stroomaf.
Verwysings
- 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/
{{#include ../banners/hacktricks-training.md}}