一句话:让 LLM 通过 MCP 调用真实工具,是"AI 挖洞"从聊天升级为实战的分水岭。
一、从 Copilot 到 Agent 的跃迁
| 形态 | 能力 | 局限 |
|---|---|---|
| 聊天 Copilot | 解释代码、生成 payload | 不接触真实环境 |
| Function Calling | 能调用预定义函数 | 需要为每个工具写适配 |
| MCP 编排 | 标准化接入任意工具 | 需要工程化 + 沙箱 |
| 自主 Agent | 自己规划多步任务 | 成本高、易失控 |
MCP(Model Context Protocol)是目前最实用的中间态:用统一协议把 nmap、httpx、fscan、sqlmap、FOFA 都包装成 LLM 可调用的工具。
二、MCP 的核心结构
┌─────────────┐
│ LLM │ 决策:下一步该调什么工具
└──────┬──────┘
│ MCP 协议
┌──────▼──────────────────────┐
│ MCP Server │
│ ├─ tool: run_nmap │
│ ├─ tool: run_httpx │
│ ├─ tool: fofa_search │
│ ├─ tool: run_sqlmap │
│ └─ tool: read_file │
└──────┬──────────────────────┘
│ 实际执行
┌──────▼──────┐
│ 真实工具链 │ ⚠️ 沙箱隔离 + 流量控制
└─────────────┘
三、一个最小可用的 MCP Server
用 Python + FastMCP 快速搭一个:
from mcp.server.fastmcp import FastMCP
import subprocess
import shlex
mcp = FastMCP("pentest-tools")
# ⚠️ 关键:白名单 + 沙箱
ALLOWED_TARGETS = ["target.example.com", "10.0.0.5"]
SAFE_DIR = "/tmp/scan-output"
def check_target(target: str) -> bool:
"""强制目标白名单校验,防止 AI 打错目标"""
return any(t in target for t in ALLOWED_TARGETS)
@mcp.tool()
def run_nmap(target: str, ports: str = "1-1000") -> str:
"""对目标执行 nmap 端口扫描。target 必须在授权范围内。"""
if not check_target(target):
return "ERROR: 目标不在授权白名单内,拒绝执行"
# 注意:参数必须用列表传递,不要拼 shell 字符串(防命令注入)
cmd = ["nmap", "-Pn", "-sV", "-p", ports, target]
r = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
return r.stdout[:8000]
@mcp.tool()
def run_httpx(targets: list[str]) -> str:
"""批量探活并抓取标题、状态码、技术栈"""
for t in targets:
if not check_target(t):
return f"ERROR: {t} 不在白名单"
# 写入临时文件后调用
with open(f"{SAFE_DIR}/targets.txt", "w") as f:
f.write("\n".join(targets))
cmd = ["httpx", "-l", f"{SAFE_DIR}/targets.txt",
"-title", "-status-code", "-tech-detect", "-silent"]
r = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
return r.stdout[:8000]
@mcp.tool()
def fofa_search(query: str, size: int = 100) -> str:
"""执行 FOFA 资产测绘查询"""
# 实际调用 FOFA API
...
if __name__ == "__main__":
mcp.run()
安全设计要点(别跳过):
- 目标白名单——防止 AI 幻觉/越界打错目标
- 参数用列表传递——防命令注入
- 输出截断——防止上下文爆炸
- 超时控制——防卡死
- 只读扫描优先——不暴露
--exploit类工具给 Agent
四、Agent 主循环设计
import json
SYSTEM_PROMPT = """
你是一名渗透测试 Agent。你可以调用工具探测目标。
目标域:example.com,已获授权。
规则:
1. 每次只调用一个工具,等待结果后再决定下一步
2. 严禁攻击白名单外的任何目标
3. 每完成一步,把结论写入 state.json
4. 发现疑似漏洞必须标记 VERIFY_REQUIRED,不要自行下结论
5. 预算上限 50 次工具调用,超出则总结退出
"""
def agent_loop(objective: str, max_steps: int = 50):
state = {"objective": objective, "steps": [], "findings": []}
for step in range(max_steps):
# 1. 让 LLM 决策
decision = llm.decide(
system=SYSTEM_PROMPT,
state=state, # 显式喂状态,防遗忘
tools=available_tools()
)
if decision["action"] == "finish":
break
# 2. 执行工具
result = call_tool(decision["tool"], decision["args"])
# 3. 让 LLM 压缩结果(防上下文爆炸)
summary = llm.summarize(result, max_tokens=500)
# 4. 更新状态
state["steps"].append({
"step": step,
"tool": decision["tool"],
"args": decision["args"],
"summary": summary,
"reasoning": decision["reasoning"]
})
# 5. 持久化(关键!)
with open("state.json", "w") as f:
json.dump(state, f, ensure_ascii=False, indent=2)
return state
三个设计精髓:
- 显式状态文件:LLM 会遗忘,用
state.json把记忆外置,每轮重新注入。 - 每步压缩:工具原始输出可能几万字符,压缩到 500 token 再入上下文。
- 强制预算:
max_steps防止 Agent 无限循环烧 token。
五、控制 Agent 不失控的五个阀门
1. 目标白名单(硬编码,AI 无法修改)
2. 工具白名单(只暴露只读/扫描类工具)
3. 速率限制(每秒请求上限)
4. 预算上限(工具调用次数 + token 上限)
5. 人工确认点(高危操作前暂停等待确认)
第 5 条尤其重要。可以这样设计:
DANGEROUS_TOOLS = {"run_sqlmap", "exploit", "write_file"}
if decision["tool"] in DANGEROUS_TOOLS:
if not human_approve(decision): # 等待人工点击确认
state["steps"].append({"skipped": decision})
continue
六、主流开源框架对比
| 框架 | 语言 | 特点 | 适用 |
|---|---|---|---|
| CAI (Cybersecurity AI) | Python | 模块化,支持多 Agent | 研究/二次开发 |
| PentestGPT | Python | 推理-执行-总结三段式 | CTF/靶场 |
| XBOW | 商业 | 产线级,主打真实漏洞 | 企业(付费) |
| Nuclei + AI 插件 | Go | 模板驱动,AI 辅助生成模板 | 批量资产 |
七、实战:Agent 打一个靶场
用户:目标 10.0.0.5,请做一次信息收集 + 漏洞验证
Agent 步骤:
[1] run_nmap(10.0.0.5) → 发现 22/80/3306 开放
[2] run_httpx(["10.0.0.5"]) → 标题 "phpMyAdmin"
[3] 推理:phpMyAdmin + 3306 → 尝试弱口令 & 已知漏洞
[4] fofa_search(...) → 不动,目标明确
[5] 人工确认点:请求执行 sqlmap?→ 用户同意
[6] run_sqlmap(...) → 无注入
[7] 推理:phpMyAdmin 版本 4.x → 检查 CVE
[8] 总结:输出 findings + 建议
注意第 5 步的人工确认——这是负责任的设计。
八、常见坑
| 坑 | 后果 | 解法 |
|---|---|---|
| 不设白名单 | AI 打错目标 | 硬编码白名单 |
| 不压缩输出 | 上下文爆炸,Agent 变傻 | 每步摘要 |
| 无预算限制 | 烧光 token | max_steps + token 预算 |
| 不记录日志 | 出事无法复盘 | 全量落库 |
| 不做沙箱 | 工具在宿主机乱跑 | Docker 隔离 |
| 轻信结论 | 幻觉漏洞进报告 | 强制人工验证 |
九、小结
MCP + Agent 是目前"AI 挖洞"最接近实战的形态,但它的价值上限取决于你的工程能力:
- 工具封装得好 → Agent 真能干活的
- 沙箱和阀门做得好 → 才敢用在真实授权环境
- 状态管理和压缩做得好 → 才跑得动长任务
别追求"全自动无人值守",追求"半自动 + 人在环"。 这是当前性价比最高的形态。
下一篇:AI 辅助漏洞报告撰写。
系列文章:AI 渗透测试与漏洞挖掘实战