Agent-Hellboy/mcpfz-probe
GitHub: Agent-Hellboy/mcpfz-probe
用于 MCP 服务器模糊测试的独立运行时探针,基于 eBPF 将系统级行为精确归因到具体工具调用,辅助发现安全风险。
Stars: 2 | Forks: 0
# mcpfz-probe
[](https://github.com/Agent-Hellboy/mcpfz-probe/actions/workflows/ci.yml)
[](https://pypi.org/project/mcpfz-probe/)
用于 MCP 服务器 fuzzing 的独立运行时探针。它运行在
[**mcp-server-fuzzer**](https://github.com/Agent-Hellboy/mcp-server-fuzzer) 旁边:
fuzzer 负责进程启动和单次调用计时;此仓库负责运行时事件
收集、单次调用归因以及 sidecar 协议。特权的
sidecar 使用 Rust 编写(体积小、可审计的 Linux 静态产物);集成层
使用 Python 编写(一个简单的 `RuntimeMonitor`)。请参阅 fuzzer 的
[运行时监控](https://github.com/Agent-Hellboy/mcp-server-fuzzer#runtime-monitoring-optional)
章节,了解这两者是如何结合在一起的。
## 安装
Python 监控器 + 策略引擎(由 fuzzer 使用):
```
pip install mcpfz-probe
```
CI 还会在每个 `v*`
tag 上发布预编译的、启用 eBPF 的 **Linux sidecar binary**。获取最新版本,并通过 `MCPFZ_PROBE_BIN` 指定 fuzzer 使用它:
```
curl -L -o mcpfz-probe \
https://github.com/Agent-Hellboy/mcpfz-probe/releases/latest/download/mcpfz-probe-x86_64-linux-ebpf
chmod +x mcpfz-probe
```
## 仓库结构
```
crates/mcpfz-probe/ Rust sidecar binary (fake + eBPF backends)
crates/mcpfz-probe-ebpf/ BPF program (compiled to bytecode, Linux only)
crates/mcpfz-probe-ebpf-common/ #[repr(C)] event type shared kernel<->userspace
src/mcpfz_probe/ Python monitor + policy engine
tests/ CI-friendly Python tests (fake backend, no root)
examples/ Sample events + live eBPF demo
docs/ Architecture and protocol notes
```
## 状态
- **Python 监控器 + 策略引擎**:已完成并经过测试。
- **`fake` backend**:已完成。这是一个确定性的测试替身,它将脚本化的事件重放到正确的 bucket(`startup`/`call`/`ambient`)中,并归因到当前的 `call_id` —— 整个 pipeline 可以在任何操作系统上无需 root 权限运行。
- **`ebpf` backend**:真实的、多探针。在 `syscalls:sys_enter_*` tracepoint 上加载 CO-RE BPF 程序 —— 包括 exec (`execve`)、网络 (`connect`, `sendto`)、文件打开 (`openat`)、删除 (`unlink`/`unlinkat`)、chmod (`chmod`/`fchmodat`) 以及 `ptrace` —— 将捕获到的事件归因到当前的调用窗口,并输出与 fake backend 相同的 NDJSON。已在 Ubuntu 24.04 / kernel 6.8 上由 `mcp-server-fuzzer` 驱动验证:一个存在漏洞的服务器产生了 exec、TCP+UDP connect、敏感读取、工作区外写入、chmod、删除以及 ptrace 探测结果,每一项都精确归因到了具体的 tool call。
## Sidecar 协议 (NDJSON)
Python → sidecar stdin (控制):
```
{"op":"scope","pgid":1234,"generation":1}
{"op":"mark","phase":"begin","call_id":"...","tool":"get_weather"}
{"op":"mark","phase":"end","call_id":"..."}
```
Sidecar → Python stdout (事件);`bucket` 为 `startup`/`call`/`ambient`:
```
{"type":"exec","bucket":"call","call_id":"...","pid":1234,"argv":["/bin/sh","-c","curl ..."]}
{"type":"connect","bucket":"ambient","pid":1234,"dst":"203.0.113.7:443"}
```
完整规范在 `docs/protocol.md` 中。
## 使用方法 (Python)
```
monitor.set_scope_pgid(server_pgid, generation=1)
monitor.begin_call(call_id, tool_name)
try:
result = call_tool(...)
finally:
summary = monitor.end_call(call_id) # events attributed to this call
findings = evaluate_events(summary.events, policy)
```
## CLI
```
mcpfz-probe --backend fake --events-file examples/events.sample.json
mcpfz-probe --backend ebpf # Linux, needs root/CAP_BPF
mcpfz-probe --help
```
`fake` backend 读取一个事件脚本(`{"events":[...]}` 或纯粹的 `[...]`),
每个条目包含一个 `trigger`(`startup`/`scope`/`begin`/`end`,可选的 `tool` 过滤器)以及一个由 sidecar 透传的 `event` 对象,并填充 `bucket`、`call_id`
和 `ts_ns`。请参阅 `examples/events.sample.json`。
## mcp-server-fuzzer 集成
该探针通过三个小巧的、可选的 hook 插入到 `mcp-server-fuzzer` 中
(模块 `mcp_fuzzer/runtime_probe.py`):在 stdio 服务器启动时,将 sidecar 的作用域限定在该服务器的进程组,在每个 `_execute_tool_call` 周围打上 `begin`/`end` 标记,并在
最后将生成的探测结果合并到会话中。如果未设置 `MCP_FUZZER_RUNTIME_PROBE`,这些 hook 将是空操作。
```
export MCP_FUZZER_RUNTIME_PROBE=1
export MCPFZ_PROBE_BIN=/path/to/mcpfz-probe # the sidecar binary
export MCPFZ_PROBE_BACKEND=ebpf # or "fake"
sudo -E mcp-fuzzer --mode tools --protocol stdio \
--endpoint "python examples/vulnerable_server.py" \
--runs 3 --max-concurrency 1
```
内核观测到的 syscall 会变成精确归因到具体 tool + run 的探测结果:
`runtime.exec`、`runtime.net_connect`、`runtime.sensitive_read`、
`runtime.fs_write`、`runtime.fs_delete`、`runtime.fs_chmod` 和
`runtime.ptrace`。已在 Linux 上针对 `examples/vulnerable_server.py`
进行了验证(这些 tool 包括执行 shell 命令、读取 `~/.ssh`、通过 TCP/UDP 进行 beacon 通信、创建+chmod+删除文件以及调用 ptrace):所有七个类别都被成功捕获并合并到了
fuzzer 的报告中,每一项都归因到了引发它的 call。
单次调用归因假设 stdio 调用是串行运行的(`--max-concurrency 1`),
这与 `docs/architecture.md` 中的设计相匹配;来自重叠调用的 exec 仍然会被
捕获到,但会被归入 `ambient` bucket。
## 开发
```
# Python 测试
PYTHONPATH=src python3 -m unittest discover -s tests
# Rust sidecar(便携、伪 backend)
cargo build
cargo test
```
### eBPF backend(Linux)
需要支持 BTF 的内核以及以下工具链:
```
rustup toolchain install nightly --component rust-src
cargo install bpf-linker # needs LLVM dev libs (e.g. llvm-18-dev)
cargo build --features ebpf # build.rs compiles the BPF crate to bytecode
sudo ./target/debug/mcpfz-probe --backend ebpf
```
实时端到端演示(真实的内核捕获 + 真实的策略),请以 root 身份运行:
```
python3 examples/ebpf_live_demo.py
```
已知限制:作用域过滤是通过在用户空间读取 `/proc//stat` 来解析进程组的,这在与短生命周期进程竞争时会产生竞态问题。根据
`docs/architecture.md`,这应该移至内核程序中
(通过 CO-RE 使用 `task->group_leader`)—— 这是下一步与 connect/file_open 探针一起要做的工作。
标签:CISA项目, Docker镜像, MCP, Python, Rust, 可视化界面, 安全测试, 攻击性安全, 无后门, 网络流量审计, 逆向工具, 通知系统