一句话:让 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()

安全设计要点(别跳过):

  1. 目标白名单——防止 AI 幻觉/越界打错目标
  2. 参数用列表传递——防命令注入
  3. 输出截断——防止上下文爆炸
  4. 超时控制——防卡死
  5. 只读扫描优先——不暴露 --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

三个设计精髓:

  1. 显式状态文件:LLM 会遗忘,用 state.json 把记忆外置,每轮重新注入。
  2. 每步压缩:工具原始输出可能几万字符,压缩到 500 token 再入上下文。
  3. 强制预算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 渗透测试与漏洞挖掘实战