Dependency Confusion
Reading time: 9 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Basic Information
Η Διαταραχή Εξάρτησης (γνωστή και ως επιθέσεις υποκατάστασης) συμβαίνει όταν ένας διαχειριστής πακέτων επιλύει ένα όνομα εξάρτησης από μια μη προοριζόμενη, λιγότερο αξιόπιστη πηγή/μητρώο (συνήθως ένα δημόσιο μητρώο) αντί για το προοριζόμενο ιδιωτικό/εσωτερικό. Αυτό συνήθως οδηγεί στην εγκατάσταση ενός πακέτου που ελέγχεται από τον επιτιθέμενο.
Κοινές ρίζες αιτίες:
- Typosquatting/ορθογραφικά λάθη: Εισαγωγή του
reqests
αντί τουrequests
(επιλύεται από δημόσιο μητρώο). - Μη υπάρχον/παρατημένο εσωτερικό πακέτο: Εισαγωγή του
company-logging
που δεν υπάρχει πια εσωτερικά, οπότε ο επιλυτής κοιτάζει σε δημόσια μητρώα και βρίσκει ένα πακέτο του επιτιθέμενου. - Προτίμηση έκδοσης σε πολλαπλά μητρώα: Εισαγωγή ενός εσωτερικού
company-requests
ενώ ο επιλυτής επιτρέπεται να ερωτά και δημόσια μητρώα και προτιμά την “καλύτερη”/νεότερη έκδοση που δημοσιεύεται δημόσια από έναν επιτιθέμενο.
Κύρια ιδέα: Εάν ο επιλυτής μπορεί να δει πολλαπλά μητρώα για το ίδιο όνομα πακέτου και επιτρέπεται να επιλέξει τον “καλύτερο” υποψήφιο παγκοσμίως, είστε ευάλωτοι εκτός αν περιορίσετε την επίλυση.
Exploitation
warning
Σε όλες τις περιπτώσεις, ο επιτιθέμενος χρειάζεται μόνο να δημοσιεύσει ένα κακόβουλο πακέτο με το ίδιο όνομα όπως η εξάρτηση που επιλύει η κατασκευή σας από ένα δημόσιο μητρώο. Οι hooks κατά την εγκατάσταση (π.χ., npm scripts) ή οι διαδρομές κώδικα κατά την εισαγωγή συχνά δίνουν εκτέλεση κώδικα.
Misspelled & Inexistent
Εάν το έργο σας αναφέρεται σε μια βιβλιοθήκη που δεν είναι διαθέσιμη στο ιδιωτικό μητρώο, και τα εργαλεία σας επιστρέφουν σε ένα δημόσιο μητρώο, ένας επιτιθέμενος μπορεί να σπείρει ένα κακόβουλο πακέτο με αυτό το όνομα στο δημόσιο μητρώο. Οι εκτελέσεις σας/CI/μηχανές ανάπτυξης θα το ανακτήσουν και θα το εκτελέσουν.
Unspecified Version / “Best-version” selection across indexes
Οι προγραμματιστές συχνά αφήνουν τις εκδόσεις μη καθορισμένες ή επιτρέπουν ευρείες γκάμες. Όταν ένας επιλυτής είναι ρυθμισμένος με εσωτερικούς και δημόσιους δείκτες, μπορεί να επιλέξει την πιο πρόσφατη έκδοση ανεξαρτήτως πηγής. Για εσωτερικά ονόματα όπως requests-company
, εάν ο εσωτερικός δείκτης έχει 1.0.1
αλλά ένας επιτιθέμενος δημοσιεύει 1.0.2
στο δημόσιο μητρώο και ο επιλυτής σας θεωρεί και τα δύο, το δημόσιο πακέτο μπορεί να κερδίσει.
AWS Fix
Αυτή η ευπάθεια βρέθηκε στο AWS CodeArtifact (διαβάστε τις λεπτομέρειες σε αυτή την ανάρτηση blog). Η AWS πρόσθεσε ελέγχους για να επισημάνει τις εξαρτήσεις/τροφές ως εσωτερικές ή εξωτερικές ώστε ο πελάτης να μην ανακτά “εσωτερικά” ονόματα από ανώτερα δημόσια μητρώα.
Finding Vulnerable Libraries
Στην αρχική ανάρτηση σχετικά με τη διαταραχή εξάρτησης, ο συγγραφέας αναζητούσε χιλιάδες εκτεθειμένα μανιφέστα (π.χ., package.json
, requirements.txt
, lockfiles) για να συμπεράνει τα εσωτερικά ονόματα πακέτων και στη συνέχεια δημοσίευσε πακέτα με υψηλότερες εκδόσεις σε δημόσια μητρώα.
Practical Attacker Playbook (for red teams in authorized tests)
- Καταγράψτε ονόματα:
- Grep repos και CI configs για μανιφέστα/lock files και εσωτερικά namespaces.
- Αναζητήστε συγκεκριμένα προθέματα οργανώσεων (π.χ.,
@company/*
,company-*
, εσωτερικά groupIds, πρότυπα NuGet ID, ιδιωτικές διαδρομές module για Go, κ.λπ.). - Ελέγξτε δημόσια μητρώα για διαθεσιμότητα:
- Εάν το όνομα δεν είναι δημόσια καταχωρημένο, καταχωρήστε το; εάν υπάρχει, προσπαθήστε να εκμεταλλευτείτε την υποεξάρτηση στοχεύοντας εσωτερικά μεταβατικά ονόματα.
- Δημοσιεύστε με προτεραιότητα:
- Επιλέξτε μια semver που “κερδίζει” (π.χ., μια πολύ υψηλή έκδοση) ή ταιριάζει στους κανόνες του επιλυτή.
- Συμπεριλάβετε ελάχιστη εκτέλεση κατά την εγκατάσταση όπου είναι εφαρμόσιμο (π.χ., npm
preinstall
/install
/postinstall
scripts). Για Python, προτιμήστε διαδρομές εκτέλεσης κατά την εισαγωγή, καθώς οι wheels συνήθως δεν εκτελούν αυθαίρετο κώδικα κατά την εγκατάσταση. - Εξαγωγή ελέγχου:
- Βεβαιωθείτε ότι επιτρέπεται η έξοδος από το CI προς το ελεγχόμενο endpoint σας; αλλιώς χρησιμοποιήστε DNS queries ή μηνύματα σφάλματος ως side-channel για να αποδείξετε την εκτέλεση κώδικα.
caution
Πάντα να αποκτάτε γραπτή εξουσιοδότηση, χρησιμοποιήστε μοναδικά ονόματα/εκδόσεις πακέτων για την εμπλοκή, και αμέσως αφαιρέστε ή συντονίστε την καθαριότητα όταν ολοκληρωθεί η δοκιμή.
Defender Playbook (what actually prevents confusion)
Στρατηγικές υψηλού επιπέδου που λειτουργούν σε οικοσυστήματα:
- Χρησιμοποιήστε μοναδικά εσωτερικά namespaces και συνδέστε τα σε ένα μόνο μητρώο.
- Αποφύγετε την ανάμειξη επιπέδων εμπιστοσύνης κατά την επίλυση. Προτιμήστε ένα μόνο εσωτερικό μητρώο που προξενεί εγκεκριμένα δημόσια πακέτα αντί να δίνετε στους διαχειριστές πακέτων τόσο εσωτερικά όσο και δημόσια endpoints.
- Για διαχειριστές που το υποστηρίζουν, χαρτογραφήστε τα πακέτα σε συγκεκριμένες πηγές (κανένα παγκόσμιο “καλύτερο-έκδοση” σε μητρώα).
- Κλειδώστε και κλειδώστε:
- Χρησιμοποιήστε lockfiles που καταγράφουν τα URLs του επιλυμένου μητρώου (npm/yarn/pnpm) ή χρησιμοποιήστε hash/attestation pinning (pip
--require-hashes
, Gradle dependency verification). - Εμποδίστε την δημόσια επιστροφή για εσωτερικά ονόματα στο επίπεδο του μητρώου/δικτύου.
- Κρατήστε τα εσωτερικά ονόματά σας σε δημόσια μητρώα όταν είναι εφικτό για να αποτρέψετε μελλοντικό squat.
Ecosystem Notes and Secure Config Snippets
Παρακάτω είναι πρακτικές, ελάχιστες ρυθμίσεις για να μειώσετε ή να εξαλείψετε τη διαταραχή εξάρτησης. Προτιμήστε να επιβάλλετε αυτές σε CI και περιβάλλοντα ανάπτυξης.
JavaScript/TypeScript (npm, Yarn, pnpm)
- Χρησιμοποιήστε scoped packages για όλο τον εσωτερικό κώδικα και κλειδώστε την εμβέλεια στο ιδιωτικό σας μητρώο.
- Διατηρήστε τις εγκαταστάσεις αμετάβλητες στο 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 (για εσωτερικό πακέτο)
{
"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:
- Δημοσιεύστε μόνο εσωτερικά πακέτα εντός του
@company
scope. - Για τρίτα πακέτα, επιτρέψτε δημόσιο μητρώο μέσω του ιδιωτικού σας proxy/mirror, όχι απευθείας από τους πελάτες.
- Σκεφτείτε να ενεργοποιήσετε την προέλευση πακέτων npm για τα δημόσια πακέτα που δημοσιεύετε για να αυξήσετε την ιχνηλασιμότητα (δεν αποτρέπει από μόνη της την σύγχυση).
Python (pip / Poetry)
Core rule: Μην χρησιμοποιείτε --extra-index-url
για να αναμειγνύετε επίπεδα εμπιστοσύνης. Είτε:
- Εκθέστε έναν μόνο εσωτερικό δείκτη που προξενεί και αποθηκεύει τα εγκεκριμένα πακέτα PyPI, είτε
- Χρησιμοποιήστε ρητή επιλογή δείκτη και pinning hash.
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
Δημιουργία καταγεγραμμένων απαιτήσεων με pip-tools:
# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt
Αν πρέπει να φτάσετε στο δημόσιο PyPI, κάντε το μέσω του εσωτερικού σας proxy και διατηρήστε μια ρητή λίστα επιτρεπόμενων εκεί. Αποφύγετε το --extra-index-url
στο CI.
.NET (NuGet)
Χρησιμοποιήστε το Package Source Mapping για να συνδέσετε τα πρότυπα ID πακέτων με ρητές πηγές και να αποτρέψετε την επίλυση από απροσδόκητες πηγές.
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 (καθρέφτης όλα στο εσωτερικό; απαγόρευση ad-hoc repos στα POMs μέσω Enforcer):
<settings>
<mirrors>
<mirror>
<id>internal-mirror</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.corp.example/repository/group</url>
</mirror>
</mirrors>
</settings>
Προσθέστε Enforcer για να απαγορεύσετε τα αποθετήρια που δηλώνονται σε POMs και να επιβάλετε τη χρήση του καθρέφτη σας:
<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: Κεντρικοποίηση και κλείδωμα εξαρτήσεων.
- Επιβολή αποθετηρίων μόνο στο
settings.gradle(.kts)
:
dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories {
maven { url = uri("https://maven.corp.example/repository/group") }
}
}
- Ενεργοποιήστε την επαλήθευση εξαρτήσεων (checksums/signatures) και δεσμεύστε το
gradle/verification-metadata.xml
.
Go Modules
Ρυθμίστε ιδιωτικά modules ώστε να μην χρησιμοποιούνται το δημόσιο proxy και η βάση δεδομένων checksums για αυτά.
# 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)
Αντικαταστήστε το crates.io με έναν εγκεκριμένο εσωτερικό καθρέφτη ή κατάλογο προμηθευτή για τις κατασκευές. Μην επιτρέπετε αυθαίρερη δημόσια εναλλακτική λύση.
.cargo/config.toml
[source.crates-io]
replace-with = "corp-mirror"
[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"
Για τη δημοσίευση, να είστε σαφείς με το --registry
και να διατηρείτε τα διαπιστευτήρια περιορισμένα στο στοχευμένο μητρώο.
Ruby (Bundler)
Χρησιμοποιήστε μπλοκ πηγών και απενεργοποιήστε τα Gemfiles πολλαπλών πηγών ώστε οι γέμισες να προέρχονται μόνο από το προορισμένο αποθετήριο.
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
Επιβολή σε επίπεδο ρύθμισης:
bundle config set disable_multisource true
CI/CD και Έλεγχοι Μητρώου που Βοηθούν
- Ιδιωτικό μητρώο ως μοναδική είσοδος:
- Χρησιμοποιήστε Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts ως το μόνο σημείο πρόσβασης που μπορούν να φτάσουν οι προγραμματιστές/CI.
- Εφαρμόστε κανόνες αποκλεισμού/επιτρεπόμενων ώστε οι εσωτερικές ονομασίες να μην επιλύονται ποτέ από δημόσιες πηγές ανάντη.
- Τα lockfiles είναι αμετάβλητα στο CI:
- npm: δεσμεύστε το
package-lock.json
, χρησιμοποιήστεnpm ci
. - Yarn: δεσμεύστε το
yarn.lock
, χρησιμοποιήστεyarn install --immutable
. - Python: δεσμεύστε το κατακερματισμένο
requirements.txt
, επιβάλετε--require-hashes
. - Gradle: δεσμεύστε το
verification-metadata.xml
και αποτύχετε σε άγνωστα αρχεία. - Έλεγχος εξόδου: αποκλείστε την άμεση πρόσβαση από το CI σε δημόσια μητρώα εκτός μέσω του εγκεκριμένου proxy.
- Κράτηση ονομάτων: προεγγραφείτε στα εσωτερικά σας ονόματα/ονομασίες σε δημόσια μητρώα όπου υποστηρίζεται.
- Προέλευση πακέτου / πιστοποιήσεις: όταν δημοσιεύετε δημόσια πακέτα, ενεργοποιήστε την προέλευση/πιστοποιήσεις για να κάνετε την παραχάραξη πιο ανιχνεύσιμη προς τα κάτω.
Αναφορές
- 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
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.