Agent-Hellboy/mcpfz-probe

GitHub: Agent-Hellboy/mcpfz-probe

用于 MCP 服务器模糊测试的独立运行时探针,基于 eBPF 将系统级行为精确归因到具体工具调用,辅助发现安全风险。

Stars: 2 | Forks: 0

# mcpfz-probe [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/Agent-Hellboy/mcpfz-probe/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/mcpfz-probe.svg)](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, 可视化界面, 安全测试, 攻击性安全, 无后门, 网络流量审计, 逆向工具, 通知系统