repowazdogz-droid/mcp-boundary-audit
GitHub: repowazdogz-droid/mcp-boundary-audit
用于检测 MCP 服务器中 tools/list 隐藏工具仍可通过 tools/call 调用的授权边界不一致漏洞的安全审计工具。
Stars: 0 | Forks: 0
# mcp-boundary-audit
[](https://github.com/repowazdogz-droid/mcp-boundary-audit/actions/workflows/ci.yml)
[](LICENSE)
[](pyproject.toml)
一个小型测试套件,用于检测 [Model
Context Protocol](https://modelcontextprotocol.io) 服务器中的一种特定授权漏洞:**对
`tools/list` 隐藏,但仍然可以通过 `tools/call` 访问的工具。**
它附带了一个内置的模拟服务器来展示该漏洞,因此只需全新克隆即可
端到端地复现该发现,无需任何第三方组件和网络。
## 这能解决什么问题?
MCP 服务器通常会限制客户端可以使用的工具——例如通过
`ALLOWED_TOOLS` 环境变量来收窄 `tools/list` 返回的内容。人们通常
会认为,没有出现在列表中的工具也同样无法被调用。
这种假设是一种*表示层*控制,只有当相同的限制也在
*执行层*(即 `tools/call`)得到强制执行时,它才是真实的。当
两层不一致时,已经知道(或猜到)工具名称的客户端就可以
调用操作员认为已关闭的功能。该测试套件用于
衡量给定服务器的这两层是否一致。
## 它能检测哪类漏洞?
MCP 工具上的表示层与执行层授权不匹配:该工具在 `tools/list` 中被过滤掉了,但 `tools/call` 依然会执行它。这正是以下安全公告中记录的漏洞特征:
[GHSA-cr22-wjx7-2w6m](https://github.com/Flux159/mcp-server-kubernetes/security/advisories/GHSA-cr22-wjx7-2w6m)
(列表过滤但未进行调用限制)。它**不能**检测提示词注入、
工具投毒、传输层身份验证漏洞,或任何需要对工具行为进行语义
理解的问题。
## 它是如何工作的?
1. 该测试套件会启动配置文件中描述的**本地** stdio MCP 服务器。
2. 它会调用 `tools/list` 并记录可见的工具。
3. 对于操作员声明*应被拒绝*且*不在列表中*的每个工具,它——仅在执行模式下——会发出一个**无害的** `tools/call`。
4. 它会对每个探测进行分类,并输出判定结果以及一个内容哈希证据文件。
| 判定结果 | 含义 |
|---|---|
| **FAIL** | 隐藏的被拒绝工具在 `tools/call` 中返回了成功。边界已被打破。 |
| **PASS** | 隐藏工具在 `tools/call` 中被授权类拒绝机制拒绝。 |
| **INCONCLUSIVE** | 调用失败,但未出现可识别的拒绝特征(如参数错误、崩溃)。永远不会作为漏洞发现报告。 |
| **SKIPPED** | 演练模式、仍在列表中的工具,或具有破坏性的工具名称。 |
安全性是内置在工具中的,而不是后期附加的:
- **默认为演练模式。** 除非您传入 `--execute`,否则不会发出任何 `tools/call`。
- `--execute` **要求**提供 `--i-own-this-server`;如果没有它,测试套件将拒绝执行。
- **默认跳过具有破坏性的工具名称**(包含十二个子字符串,例如
`delete`、`exec`、`write`)。即使在执行模式下,测试套件也不会调用它们。
- 每个报告都会记录 `operator_asserted_ownership`、`local_only`、报告的
内容哈希以及配置的哈希值,因此运行过程是可重放的,并且其
授权事宜在事后也是可审计的。
## 我该如何复现它?
```
pip install -e ".[dev]"
```
针对内置的**易受攻击的**模拟服务器运行审计(安全:每个工具都是
无害的字符串函数):
```
cd examples
mcp-boundary-audit --config vulnerable_server.config.json --execute --i-own-this-server
```
预期结果:`Verdict: FAIL`,其中 `ping` 和 `whoami` 被报告为可调用,尽管
它们并未出现在 `tools/list` 中(该列表仅显示 `echo`)。
现在测试**已修复的**服务器,其白名单在两个层面上都得到了强制执行:
```
mcp-boundary-audit --config patched_server.config.json --execute --i-own-this-server
```
预期结果:`Verdict: PASS` —— 相同的隐藏工具在 `tools/call` 处被拒绝。
整个交互过程也被编写成了测试:
```
pytest -q
```
`tests/test_end_to_end.py` 会针对两种模式运行测试套件,并断言
依次出现 FAIL 和 PASS。`tests/test_units.py` 涵盖了分类逻辑,包括
如果拒绝消息未被启发式算法识别,则会被计为 INCONCLUSIVE,而
不是 FAIL,从而确保工具无法利用未知的错误字符串捏造漏洞发现。
## 它有哪些局限性?
- **仅支持 stdio 传输。** HTTP/SSE 服务器不在范围内。
- **破坏性名称过滤器是一种启发式方法**,而非语义分析。它通过
子字符串进行跳过;它并不理解工具的具体作用。
- **授权拒绝是通过错误消息关键字来检测的。** 如果服务器的
拒绝措辞超出了 [`AUTH_DENIAL_MARKERS`](src/mcp_boundary_audit/audit.py)
的范围,将被计为 INCONCLUSIVE 而不是 PASS。这种设计偏向于避免错误发现,而
宁愿产生错误的 INCONCLUSIVE。
- 它仅测试**一个**边界。PASS 仅表示在探测的工具中未
观察到这种特定的列表/调用不匹配。它并不代表服务器是安全的。它不
检查 OAuth、token 作用域、多租户隔离或 `readOnlyHint`
的真实性。
- 判定结果仅描述了您在所执行的运行中配置为 `denied` 的工具。它
不会为您枚举服务器的所有工具。
有关完整范围,请参阅 [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) 和
[`docs/ASSURANCE_BOUNDARY.md`](docs/ASSURANCE_BOUNDARY.md);有关双层
模型,请参阅 [`docs/AUTHORIZATION_MODEL.md`](docs/AUTHORIZATION_MODEL.md)。
## 负责任的使用
仅对您**拥有**或获得**明确书面授权**进行测试的服务器运行此
操作,并指向非生产数据。`--i-own-this-server` 标志是一个
刻意的减速带,而非许可证。您有责任遵守任何
项目的规则以及当地法律。如果针对第三方服务器的 `FAIL` 结果
是真实的,请使用该测试套件生成的最小证据集,通过该项目的安全渠道进行披露
—— 切勿率先公开可用的绕过方法。
## 许可证
[MIT](LICENSE).
标签:MCP协议, Python, 安全规则引擎, 授权漏洞检测, 无后门, 自动化测试工具, 逆向工具