Den-Sec/mcpsnare
GitHub: Den-Sec/mcpsnare
mcpsnare 是一款针对 MCP 服务器的主动安全扫描工具,通过带外确认和分级置信度机制验证真实可利用漏洞,而非静态模式匹配。
Stars: 0 | Forks: 0
# mcpsnare
**针对 MCP 服务器的主动安全扫描工具 —— _Model Context Protocol 领域的 Burp Active Scan。_**
[](https://github.com/Den-Sec/mcpsnare/actions/workflows/ci.yml)
[](https://pypi.org/project/mcpsnare/)
[](https://www.python.org/)
[](LICENSE)
mcpsnare 会枚举 MCP 服务器暴露的工具,向其参数发送针对性的 payload,
并且**只报告能够被证实的内容**。每一项发现都关联到一个具体的
oracle —— 一个带外 callback、一个被反射的 canary 值、或是一个精确校准的时序延迟 ——
并带有分级的置信度级别。
大多数“MCP 安全”工具只是在配置和源代码中进行模式匹配。而 mcpsnare **触发
漏洞并捕获证据**:一个 `CONFIRMED` 级别的发现是可利用的,而非理论上的推测。
## 演示
对易受攻击的 MCP 服务器进行默认扫描 —— 无需配置,只需一条命令:
```
$ mcpsnare scan --stdio "python vulnerable_server.py"
[!] mcpsnare - authorized testing only.
6 finding(s):
[HIGH] Path traversal in read_doc.path (confirmed)
[HIGH] Secret/info leak via whoami (firm)
[HIGH] Path traversal in read_cfg.config.path (confirmed)
[HIGH] Path traversal in read_many.paths[0] (confirmed)
[HIGH] Path traversal in read_mode.path (confirmed)
[CRITICAL] Command injection in ping.host (confirmed)
```
那个 `CRITICAL` 级别的命令注入之所以被 `confirmed`(确认),是因为注入的 payload 使
目标向 mcpsnare 控制的监听器发起了 callback —— 这是一个**执行代码的带外证明**,
而不是猜测。同一次扫描的机器可读 JSON 格式(或 SARIF / Markdown)如下:
```
$ mcpsnare scan --stdio "python vulnerable_server.py" --output json
{
"summary": { "critical": 1, "high": 5, "medium": 0, "low": 0, "info": 0 },
"findings": [
{
"check": "path_traversal", "tool": "read_doc", "param": "path",
"severity": "high", "confidence": "confirmed", "cwe": "CWE-22",
"title": "Path traversal in read_doc.path",
"payload": "../../../../../../etc/passwd",
"evidence": "root:x:0:0:root:/root:/bin/bash",
"remediation": "Resolve and contain paths within an allowed base dir."
}
/* ... */
]
}
```
## 安装
```
pipx install mcpsnare # isolated CLI (recommended)
# 或
pip install mcpsnare
```
从源码安装(开发模式):
```
git clone https://github.com/Den-Sec/mcpsnare && cd mcpsnare
pip install -e ".[dev]"
```
两种方式都会安装 `mcpsnare` 控制台入口。需要 Python 3.11+。
## 快速入门
```
# Local stdio server(作为 subprocess 启动)
mcpsnare scan --stdio "python server.py"
# Remote streamable-HTTP endpoint,带 auth,为 code scanning 发出 SARIF
mcpsnare scan --http https://host/mcp --header "Authorization: Bearer X" --output sarif
# 添加基于时间的 blocking probes(默认关闭)并调整 concurrency
mcpsnare scan --stdio "python server.py" --aggressive --concurrency 8
```
## 为什么选择 mcpsnare
大多数 MCP 安全工具要么是通用的 fuzzer(充满噪声,信噪比低),要么是
防御性/静态分析工具(只读取配置和源代码,从不证明可利用性)。
mcpsnare 的核心设计理念是主动确认:
- **有 oracle 支撑,而非盲目猜测。** 每一项发现都关联到一个具体的信号:
一个**带外 (OOB)** callback、一个**精确校准的计时**延迟、一个在响应中被反射的 **canary** 值,
或一个**基线差异 (baseline diff)**。没有信号,就没有发现。
- **分级且校准过的置信度。** 发现会带有明确的置信度级别
(**CONFIRMED / FIRM / TENTATIVE**,参见[置信度级别](#confidence-levels))。
针对每个工具的基线校准抑制了常见的误报类别 ——
一个运行缓慢但安全的工具,或者仅仅看起来像是机密形状的输出,都不会被标记。
- **触及真实的 schema。** 通过嵌套对象、数组项,
以及隐藏在必填枚举后的参数映射注入点;构建符合 schema 的基线,使 payload
能够真正抵达 handler。
- **支持双传输模式。** 适用于基于 **stdio**(本地进程)和
**流式 HTTP**(远程端点,支持自定义 headers/auth)的 MCP 服务器 —— 两者均已在 Linux 和 Windows 平台的 CI 中进行了端到端测试。
## 置信度级别
每一项发现都带有三个置信度级别之一,每个级别都通过特定的 oracle 获取:
| 级别 | 含义 | 如何获取 |
| ---------- | --------------------------------------------------- | --------------- |
| **CONFIRMED** | payload 已明确执行,或触及了受保护的数据。 | 触发了带外 callback(命令注入、SSRF),读取到了 canary 值(路径穿越),或是一个未经身份验证的调用返回了与已验证调用在字节上完全相同的响应(身份验证绕过)。 |
| **FIRM** | 校准/推断出的信号强烈暗示存在该问题,但尚未达到带外证明的程度。 | 响应延迟超过了针对单个工具校准后的基线,且超时时间与注入的休眠时间一致(基于时间的命令注入);探针响应中出现了类似机密形状的字符串,但在良性基线中不存在(信息泄露);或者是未经身份验证的响应在剥离了诸如时间戳/ID 等易变字段后,与经过身份验证的响应相匹配(身份验证绕过)。 |
| **TENTATIVE** | 仅有模式匹配,没有经过校准来佐证。 | 匹配到了类似机密形状的字符串,但没有可用的基线来证明是由输入触发的 —— 需要人工审查。 |
OOB 和 canary 检查只会发出 **CONFIRMED** 级别。身份验证绕过在响应字节完全相同时发出 **CONFIRMED**,
或在剥离易变字段后匹配成功时发出 **FIRM**。
计时和信息泄露的 oracle 是产生 **FIRM** 和 **TENTATIVE** 级别发现的地方。
## 检查项
| 检查项 | 漏洞 | CWE |
| ---------------- | ------------------------------ | -------- |
| `cmd_injection` | 操作系统命令注入 | CWE-78 |
| `ssrf` | 服务端请求伪造 (SSRF) | CWE-918 |
| `path_traversal` | 路径穿越 | CWE-22 |
| `auth_bypass` | 缺失身份验证 | CWE-306 |
| `info_leak` | 机密 / 敏感信息泄露 | CWE-200 |
| `sql_injection` | SQL 注入 | CWE-89 |
mcpsnare 还会枚举 MCP **资源模板**,并将它们带有模板的 URI
参数(例如 `file:///{path}`)视为路径穿越和信息泄露的注入点。
## 带外 (OOB) 确认
OOB callback 是 mcpsnare 确认盲注命令注入和 SSRF 的方式:探针
会促使目标反向连接到 mcpsnare 控制的监听器。
- `--oob local`(默认)会在 localhost 上启动一个进程内的 HTTP 监听器。它
不需要任何外部服务,适用于能够访问您所在主机的目标
(通常是本地的 stdio 服务器)。
- `--oob interactsh` 会使用一个带外交互服务器,适用于
无法访问 localhost 的目标(例如远程 HTTP 服务器)。mcpsnare 内置了真实的 interactsh
客户端 (RSA-OAEP / AES-256-CTR),因此无需额外配置即可针对公开的
`oast.fun` 运行(可使用 `--interactsh-server` 覆盖);且已通过端到端的实际验证。
请参阅 [docs/interactsh-runbook.md](docs/interactsh-runbook.md)。
- `--oob none` 会禁用 OOB 确认;仅运行基于时间的计时 oracle 和 canary oracle。
## 标志位
- `--stdio ""` / `--http ` — 指定目标传输协议(必填其一)。
- `--header "k:v"` — 添加一个 HTTP 标头(可多次重复使用)。
- `--oob {local,interactsh,none}` — OOB 确认后端(默认为 `local`)。
- `--aggressive` — 同时发送阻塞性的基于时间的 (sleep) 探针;默认情况下,mcpsnare
仅发送非阻塞的 OOB/canary/模式匹配探针(基于时间的检测仅在 aggressive 模式下进行)。
- `--concurrency N` — 最大并发探针请求数(默认为 4)。基于时间的探针将以串行方式运行。
- `--rate R` — 将频率限制为每秒 R 个请求(默认为无限制)。
- `--oob-timeout S` / `--oob-poll-interval S` — 轮询 OOB callback 的持续时间(默认 20 秒)/ 频率(默认 2.5 秒)。
- `--output {console,json,sarif,md}` — 输出格式(默认为 `console`)。
## 仅限授权测试
**mcpsnare 是一款主动扫描工具。它会向目标发送真实的、具有潜在破坏性的 payload。**
请仅在您拥有或获得明确书面授权进行测试的系统上运行它。
未经授权的使用可能是违法的。您需对如何使用此工具负责。
## 验证
mcpsnare 已通过自动化测试套件(119 个测试)针对 `tests/fixtures/` 中内置的
故意设计为带有漏洞的测试服务器进行了验证。该套件测试了
命令注入(包括跨操作系统的 cmd.exe / PowerShell payload)、SSRF、路径
穿越、信息泄露、SQL 注入、嵌套/数组/枚举注入点,并在端到端层面上测试了 OOB、
基线校准以及误报抑制的逻辑 —— 测试环境在 CI 中的 Linux 和 Windows 平台上覆盖了 **两种**
传输模式(stdio 以及实时进程内流式 HTTP 服务器)。声明与测试的
映射关系请参见 [docs/claims-matrix.md](docs/claims-matrix.md)。
它还针对真实的 `@modelcontextprotocol/server-everything`
参考服务器(13 个工具,2 个资源模板)进行了冒烟测试 —— 运行正常,零误报。请参见
[docs/smoke-run.md](docs/smoke-run.md)。
## 路线图
- 针对 MCP 的专项检查:通过工具描述进行工具投毒 / prompt 注入,
以及工具作用域 / 权限边界违规。
- 更多 OOB 提供程序和更丰富的基于时间的 oracle。
## 许可证
MIT — 详见 [LICENSE](LICENSE)。
标签:DNS 反向解析, DOE合作, MCP, Python, StruQ, 带外验证, 无后门, 网络安全审计, 逆向工具