Translated ['', 'src/pentesting-web/dependency-confusion.md'] to pl

This commit is contained in:
Translator 2025-08-21 02:42:08 +00:00
parent 8cd656bb33
commit e2552b1eaa

View File

@ -5,41 +5,268 @@
## Basic Information
W skrócie, luka w zależności z powodu pomyłki występuje, gdy projekt używa biblioteki o **błędnie napisanej** nazwie, **nieistniejącej** lub z **niesprecyzowaną wersją**, a używane repozytorium zależności pozwala na **zbieranie zaktualizowanych wersji z publicznych** repozytoriów.
Dependency Confusion (znane również jako ataki substytucyjne) występuje, gdy menedżer pakietów rozwiązuje nazwę zależności z niezamierzonego, mniej zaufanego rejestru/źródła (zwykle publicznego rejestru) zamiast zamierzonego prywatnego/wewnętrznego. Zwykle prowadzi to do zainstalowania pakietu kontrolowanego przez atakującego.
Typowe przyczyny:
- Typosquatting/błędne pisanie: Importowanie `reqests` zamiast `requests` (rozwiązuje z publicznego rejestru).
- Nieistniejący/porzucony wewnętrzny pakiet: Importowanie `company-logging`, który już nie istnieje wewnętrznie, więc resolver szuka w publicznych rejestrach i znajduje pakiet atakującego.
- Preferencje wersji w różnych rejestrach: Importowanie wewnętrznego `company-requests`, podczas gdy resolver ma również prawo do zapytań w publicznych rejestrach i preferuje „najlepszą” / nowszą wersję opublikowaną publicznie przez atakującego.
Kluczowa idea: Jeśli resolver może zobaczyć wiele rejestrów dla tej samej nazwy pakietu i ma prawo wybrać „najlepszego” kandydata globalnie, jesteś narażony, chyba że ograniczysz rozwiązywanie.
- **Błędnie napisana**: Import **`reqests`** zamiast `requests`
- **Nieistniejąca**: Import `company-logging`, wewnętrznej biblioteki, która **już nie istnieje**
- **Niesprecyzowana wersja**: Import **wewnętrznej** **istniejącej** biblioteki `company-requests`, ale repozytorium sprawdza **publiczne repozytoria**, aby zobaczyć, czy są **nowsze wersje**.
## Exploitation
> [!WARNING]
> W każdym przypadku atakujący musi tylko opublikować **złośliwy pakiet o nazwie** bibliotek używanych przez firmę ofiary.
> W każdym przypadku atakujący musi tylko opublikować złośliwy pakiet o tej samej nazwie, co zależność, którą twoja kompilacja rozwiązuje z publicznego rejestru. Hooki w czasie instalacji (np. skrypty npm) lub ścieżki kodu w czasie importu często dają możliwość wykonania kodu.
### Misspelled & Inexistent
Jeśli twoja firma próbuje **zaimportować bibliotekę, która nie jest wewnętrzna**, istnieje duże prawdopodobieństwo, że repozytorium bibliotek będzie jej szukać w **publicznych repozytoriach**. Jeśli atakujący ją stworzył, twój kod i działające maszyny prawdopodobnie zostaną skompromitowane.
Jeśli twój projekt odnosi się do biblioteki, która nie jest dostępna w prywatnym rejestrze, a twoje narzędzia wracają do publicznego rejestru, atakujący może umieścić złośliwy pakiet o tej nazwie w publicznym rejestrze. Twoje maszyny wykonawcze/CI/deweloperskie pobiorą i wykonają go.
### Unspecified Version
### Unspecified Version / “Best-version” selection across indexes
Programiści często pozostawiają wersje nieprzypisane lub pozwalają na szerokie zakresy. Gdy resolver jest skonfigurowany z zarówno wewnętrznymi, jak i publicznymi indeksami, może wybrać najnowszą wersję niezależnie od źródła. Dla wewnętrznych nazw, takich jak `requests-company`, jeśli wewnętrzny indeks ma `1.0.1`, ale atakujący publikuje `1.0.2` w publicznym rejestrze i twój resolver bierze pod uwagę obie, pakiet publiczny może wygrać.
Bardzo często programiści **nie określają żadnej wersji** używanej biblioteki lub określają tylko **główną wersję**. Wtedy interpreter spróbuje pobrać **najnowocześniejszą wersję** spełniającą te wymagania.\
Jeśli biblioteka jest **znaną zewnętrzną biblioteką** (jak python `requests`), **atakujący nie może wiele zrobić**, ponieważ nie będzie w stanie stworzyć biblioteki o nazwie `requests` (chyba że jest jej oryginalnym autorem).\
Jednak jeśli biblioteka jest **wewnętrzna**, jak `requests-company` w tym przykładzie, jeśli **repozytorium biblioteki** pozwala na **sprawdzanie nowych wersji również zewnętrznie**, będzie szukać nowszej wersji dostępnej publicznie.\
Więc jeśli **atakujący wie**, że firma używa biblioteki `requests-company` **wersja 1.0.1** (pozwala na drobne aktualizacje). Może **opublikować** bibliotekę `requests-company` **wersja 1.0.2**, a firma **użyje tej biblioteki zamiast** wewnętrznej.
## AWS Fix
Ta luka została znaleziona w AWS **CodeArtifact** (przeczytaj [**szczegóły w tym poście na blogu**](https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d)).\
AWS naprawiło to, pozwalając na określenie, czy biblioteka jest wewnętrzna czy zewnętrzna, aby uniknąć pobierania wewnętrznych zależności z zewnętrznych repozytoriów.
Ta podatność została znaleziona w AWS CodeArtifact (przeczytaj szczegóły w tym poście na blogu). AWS dodało kontrole, aby oznaczyć zależności/źródła jako wewnętrzne lub zewnętrzne, aby klient nie pobierał „wewnętrznych” nazw z upstream publicznych rejestrów.
## Finding Vulnerable Libraries
W [**oryginalnym poście o zależności z powodu pomyłki**](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610) autor przeszukał tysiące ujawnionych plików package.json zawierających zależności projektów javascript.
W oryginalnym poście na temat zamieszania z zależnościami autor szukał tysięcy ujawnionych manifestów (np. `package.json`, `requirements.txt`, pliki blokady), aby wywnioskować wewnętrzne nazwy pakietów, a następnie publikował pakiety o wyższych wersjach w publicznych rejestrach.
## References
## 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 (e.g., `@company/*`, `company-*`, internal groupIds, NuGet ID patterns, private module paths for Go, etc.).
- Check public registries for availability:
- If the name is unregistered publicly, register it; if it exists, attempt subdependency hijacking by targeting internal transitive names.
- Publish with precedence:
- Choose a semver that “wins” (e.g., a very high version) or matches resolver rules.
- Include minimal install-time execution where applicable (e.g., npm `preinstall`/`install`/`postinstall` scripts). For Python, prefer import-time execution paths, as wheels typically dont execute arbitrary code on install.
- Exfil control:
- Ensure outbound is allowed from CI to your controlled endpoint; otherwise use DNS queries or error messages as a side-channel to prove code execution.
> [!CAUTION]
> Always get written authorization, use unique package names/versions for the engagement, and immediately unpublish or coordinate cleanup when testing concludes.
## Defender Playbook (what actually prevents confusion)
High-level strategies that work across ecosystems:
- Use unique internal namespaces and bind them to a single registry.
- Avoid mixing trust levels at resolution time. Prefer a single internal registry that proxies approved public packages instead of giving package managers both internal and public endpoints.
- For managers that support it, map packages to specific sources (no global “best-version” across registries).
- Pin and lock:
- Use lockfiles that record the resolved registry URLs (npm/yarn/pnpm) or use hash/attestation pinning (pip `--require-hashes`, Gradle dependency verification).
- Block public fallback for internal names at the registry/network layer.
- Reserve your internal names in public registries when feasible to prevent future squat.
## Ecosystem Notes and Secure Config Snippets
Below are pragmatic, minimal configs to reduce or eliminate dependency confusion. Prefer enforcing these in CI and developer environments.
### JavaScript/TypeScript (npm, Yarn, pnpm)
- Use scoped packages for all internal code and pin the scope to your private registry.
- Keep installs immutable in 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 (dla wewnętrznego pakietu)
```
{
"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:
- Publikuj tylko wewnętrzne pakiety w obrębie zakresu `@company`.
- W przypadku pakietów zewnętrznych, zezwól na publiczny rejestr za pośrednictwem swojego prywatnego proxy/lustra, a nie bezpośrednio z klientów.
- Rozważ włączenie pochodzenia pakietów npm dla publicznych pakietów, które publikujesz, aby zwiększyć śledzenie (samo w sobie nie zapobiega pomieszaniu).
### Python (pip / Poetry)
Zasada podstawowa: Nie używaj `--extra-index-url`, aby mieszać poziomy zaufania. Albo:
- Udostępnij jeden wewnętrzny indeks, który proxy i buforuje zatwierdzone pakiety PyPI, albo
- Użyj jawnego wyboru indeksu i przypinania haszy.
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
```
Wygeneruj zhaszowane wymagania za pomocą pip-tools:
```
# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt
```
Jeśli musisz uzyskać dostęp do publicznego PyPI, zrób to przez swój wewnętrzny proxy i utrzymuj tam wyraźną listę dozwolonych źródeł. Unikaj `--extra-index-url` w CI.
### .NET (NuGet)
Użyj mapowania źródeł pakietów, aby powiązać wzorce identyfikatorów pakietów z wyraźnymi źródłami i zapobiec rozwiązywaniu z nieoczekiwanych źródeł.
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 (lustro wszystko do wewnętrznego; zabroń repozytoriów ad-hoc w POM-ach za pomocą Enforcer):
```
<settings>
<mirrors>
<mirror>
<id>internal-mirror</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.corp.example/repository/group</url>
</mirror>
</mirrors>
</settings>
```
Dodaj Enforcer, aby zablokować repozytoria zadeklarowane w POM-ach i wymusić użycie swojego lustra:
```
<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: Centralizuj i zablokuj zależności.
- Wymuszaj repozytoria tylko w `settings.gradle(.kts)`:
```
dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
maven { url = uri("https://maven.corp.example/repository/group") }
}
}
```
- Włącz weryfikację zależności (sumy kontrolne/podpisy) i zatwierdź `gradle/verification-metadata.xml`.
### Go Modules
Skonfiguruj prywatne moduły, aby publiczny proxy i baza danych sum kontrolnych nie były używane dla nich.
```
# 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)
Zastąp crates.io zatwierdzonym wewnętrznym lustrem lub katalogiem dostawcy dla kompilacji; nie zezwalaj na dowolne publiczne zapasowe źródło.
.cargo/config.toml
```
[source.crates-io]
replace-with = "corp-mirror"
[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"
```
Aby opublikować, bądź dokładny z `--registry` i ogranicz dane uwierzytelniające do docelowego rejestru.
### Ruby (Bundler)
Użyj bloków źródłowych i wyłącz multisource Gemfiles, aby gemy pochodziły tylko z zamierzonego repozytorium.
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
```
Wymuś na poziomie konfiguracji:
```
bundle config set disable_multisource true
```
## CI/CD i Kontrole Rejestru, Które Pomagają
- Prywatny rejestr jako pojedynczy punkt dostępu:
- Użyj Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts jako jedynego punktu, do którego mogą uzyskać dostęp deweloperzy/CI.
- Wprowadź zasady blokowania/zezwalania, aby wewnętrzne przestrzenie nazw nigdy nie były rozwiązywane z publicznych źródeł upstream.
- Pliki blokad są niemutowalne w CI:
- npm: zatwierdź `package-lock.json`, użyj `npm ci`.
- Yarn: zatwierdź `yarn.lock`, użyj `yarn install --immutable`.
- Python: zatwierdź haszowany `requirements.txt`, wymuś `--require-hashes`.
- Gradle: zatwierdź `verification-metadata.xml` i niepowodzenie w przypadku nieznanych artefaktów.
- Kontrola wychodzącego ruchu: zablokuj bezpośredni dostęp z CI do publicznych rejestrów, z wyjątkiem zatwierdzonego proxy.
- Rezerwacja nazw: wstępnie zarejestruj swoje wewnętrzne nazwy/przestrzenie nazw w publicznych rejestrach, gdzie to możliwe.
- Pochodzenie pakietów / zaświadczenia: podczas publikowania publicznych pakietów włącz pochodzenie/zaświadczenia, aby uczynić manipulacje bardziej wykrywalnymi w dalszej kolejności.
## Odniesienia
- [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}}