AIMap:Agentic时代的 nmap
AIMap 把「公网 AI 服务暴露面」变成一张可查询、可打分、可验证的地图。 32 条 Shodan 查询负责把 MCP Server、Ollama、vLLM 这类暴露在公网上的 AI 服务找出来;Nuclei 模板验明协议、枚举工具和系统提示;0–10 风险打分按暴露程度排序;最后按协议跑攻击验证危害。扫描引擎是纯确定性的——官方宣称的「AI 驱动攻击分析」目前只有配置占位,没有代码调用。
一、它解决什么问题
过去一年公网 AI 服务的暴露面在快速扩大:跑在内网的 MCP Server、Ollama、vLLM 被直接映射到公网,很多默认无鉴权。对攻击者来说,这是「自带工具调用的开放 API」;对防御者来说,这是自己看不见的攻击面。
问题在于传统测绘工具不认识这些协议:
| 工具 | 发现方式 | 认识 AI 协议 | 枚举暴露能力 | 攻击验证 |
|---|---|---|---|---|
| Shodan 裸搜 | 关键词、端口 | 部分,靠 banner 猜 | 否 | 否 |
| 通用漏扫 | 已知目标 + CVE 模板 | 否 | 否 | 按模板打 |
| AIMap | 32 条专用查询 | 11 类协议 | 工具 / 模型 / 系统提示 | 按协议脚本化 |
AIMap 的官方 slogan 是「nmap for the Agentic Era」:像 nmap 一样主动探测,但结论落在「这是个 MCP Server,暴露了 14 个工具,其中 2 个能执行命令」这个粒度上,而不是「8000 端口开着」。
二、流水线四步
| 阶段 | 做什么 | 输入 → 输出 |
|---|---|---|
| Discover | Shodan 查询拉取候选主机,httpx 存活过滤 | 查询词 / CIDR → 存活端点 |
| Fingerprint | Nuclei 模板 + 实时 HTTP 探测:协议、框架、鉴权、工具、模型、系统提示 | 端点 → 结构化指纹 |
| Score | 按暴露因子算 0–10 风险分 | 指纹 → 分数 + 因子清单 |
| Test | 按协议选攻击引擎,结果经 WebSocket 实时流回 | 目标 → 发现 + 请求响应证据 |
指纹这步用三路证据交叉:Shodan banner 解析(Server 头推断框架、状态码推断鉴权)、Nuclei 发现归一化(5 个自定义模板)、实时探测(对 /api/tags、/v1/models 这类协议固定路径发轻量请求,8 秒超时)。三路证据谁先拿到写谁的字段,比如系统提示从 MCP initialize 响应或提示泄漏模板里抽,抽到就打标记。
三、32 条查询都查什么
查询词按 11 类协议组织:
| 协议 | 检测特征 | 查询示例 |
|---|---|---|
| MCP | JSON-RPC + capabilities、/mcp/sse | "Model Context Protocol" |
| Ollama | 端口 11434、banner 特征 | port:11434 "Ollama is running" |
| OpenAI 兼容 | /v1/models、/v1/chat/completions | http.html:"/v1/models" port:8000 |
| LangServe | playground 标记 | http.html:"langserve" "playground" |
| OpenClaw | 控制面板标题、18789 端口 | http.title:"Clawdbot Control" |
| Open WebUI / LibreChat | 页面标题 | http.title:"Open WebUI" |
| Gradio | 标题、页脚水印、favicon hash | http.favicon.hash:945408572 |
| Streamlit | 标题、favicon hash | http.favicon.hash:-335242539 |
| ComfyUI / SD WebUI | 标题、端口 | http.title:"ComfyUI" |
| HuggingFace TGI | HTML 标记 | http.html:"huggingface" http.html:"model" |
| 通用推理 | /api/generate、/api/tags | http.html:"/api/generate" |
这些词不是拍脑袋写的。代码注释列了来源:Knostic 的 MCP-Scanner 研究、Praetorian 的 Julius LLM 指纹、Cisco / SentinelOne / FuzzingLabs 的 Ollama 暴露面报告、UpGuard 的 Streamlit / ComfyUI 暴露报告——查询词库本质上是行业暴露面研究的合集。
两个读码细节:README 的协议表只列了 30 条查询对应的行,代码里实际是 32 条,多出来的是 oobabooga 的 text-generation-webui 和一条通用的 /v1/chat/completions 查询。反过来,banner 识别代码里有 autogen 分支,查询预设里却没有 autogen 条目——能认,不能主动搜。
四、风险评分怎么算
评分权重全部实测自 compute_risk_score:
| 因子 | 加分 |
|---|---|
| 无鉴权 | +4.0 |
| 鉴权状态未知 | +1.0 |
| 暴露工具 ≥10 个 | +2.0 |
| 暴露工具 ≥5 个 | +1.0 |
| 每个 critical 级工具 | +1.0 |
| 每个 high 级工具 | +0.5 |
CORS 全开(*) |
+1.0 |
| 无 TLS | +0.5 |
| 系统提示泄漏 | +0.5 |
| 模型清单暴露 | +1.0 |
| 检出未审查模型 | +2.0 |
| 开放注册 | +1.5 |
| 危险组合(每项) | +1.0 |
总分截断到 0–10,分级:critical ≥9.0、high 7.0–8.9、medium 4.0–6.9、low 1.0–3.9、info <1.0。
设计上值得注意的:无鉴权一票 +4 是最大单因子,符合「裸挂的 AI 服务就是最高危」的直觉;鉴权未知 +1,让没验出来的端点不至于分数过低被淹没;危险组合独立加分,包括无鉴权 + 命令执行工具(exec_no_auth)、数据库读写齐全(db_read_write)、文件读写齐全(file_read_write)。
评分部分三个读码发现:
- 鉴权判定太粗:状态码 200 直接判「无鉴权」。很多登录墙服务的首页也返回 200,会被标成 no_auth 并 +4 分——列表里会混进假的裸奔服务。
- 组合检测靠子串匹配:工具名里带 “admin” 就触发 admin_no_auth,一个叫 manage_notes 的工具会被当成管理员工具。
- 截断饱和:总分到 10 截断,14 分的端点和 10 分的端点显示同分,排序失去区分度。
五、攻击引擎
MCP 引擎七个阶段:
| 阶段 | 做法 | 成功判定 |
|---|---|---|
| 侦察 | initialize 握手 + tools/list,正则把工具分成 8 类 | — |
| 未鉴权调用 | 按深度取前 N 个工具,用 schema 造最小参数逐个调用 | 响应不含鉴权错误关键词 |
| 敏感文件读取 | 对 file_read 类工具打 /etc/passwd、.env、/proc/self/environ 等 | 响应命中内容特征 |
| 命令执行 | 对 exec 类工具跑 id、whoami、env 等 | 响应含 uid=、/bin/ 等 |
| SSRF | 对 http 类工具打云元数据地址 | 响应含元数据特征 |
| 提示注入 | 对字符串参数打 6 组注入载荷 | 响应命中 14 个特征词中的 ≥2 个 |
| 数据库提取 | 对 db 类工具打 6 组 SQL 载荷 | 响应含表结构特征或语法错误 |
深度分 quick / standard / deep / exhaustive 四档,默认 standard、上限 20 步,每步间隔 0.2 秒。SSRF 目标包含 169.254.169.254、Google 云元数据、阿里云 100.100.100.200 和 localhost。Ollama 引擎的套路是模型清单、权重提取、提示注入;OpenClaw 引擎针对控制面板。
攻击部分一个读码发现:成功判定全是关键词启发式,且兜底规则很宽——比如文件读取,只要响应非错误且非空(字符串 >20 字符、列表非空)就判成功。正常业务响应经常满足这个条件。这套引擎的定位是快速筛出「明显有问题」的目标,不是替代人工复核的判决器;跑完的结果仍要逐条人工核实。
六、AI 在哪
README 和环境变量里都有 ANTHROPIC_API_KEY,注释写着「可选,启用 AI 驱动的攻击分析」;ROADMAP 的愿景也写着「Autonomous red-team agent (Claude-powered):拿到指纹后针对目标推理攻击链、产出利用证据」。但读遍当前代码:这个 key 只在 config.py 里声明,在 .env.example 和 Modal 部署文档里出现,没有任何一行代码读取它。攻击引擎是写死的脚本,没有模型调用。
所以「AI」目前只存在于路线图里。这反而是设计上诚实的地方:发现、指纹、评分这些环节不需要模型,确定性规则更可控、可复现;真正难自动化的「读指纹、推理攻击链」被留在 ROADMAP 里。别被「AI-powered」字样误导。
七、怎么用起来
docker compose 起 4 个服务(MongoDB、Redis、FastAPI 后端、前端),.env 里最少填 SHODAN_API_KEY;Redis 可缺省降级为内存实现,Nuclei 只在主动扫描时需要单独装。扫描分两种:发现扫描(查询预设或自定义 Shodan 查询,可选 CIDR 范围)和主动扫描(对指定 IP 段跑 httpx + 自定义模板,默认端口 80/443/3000/8000/8080/8443/8888)。
搜索结果用 Shodan 风格语法:
| 语法 | 含义 |
|---|---|
protocol:mcp auth:none |
无鉴权的 MCP Server |
risk:critical tool:exec_code |
带命令执行工具的高危端点 |
has:system_prompt |
泄漏了系统提示的端点 |
country:US port:11434 |
美国暴露的 Ollama |
并发限制:同时最多 3 个扫描、5 个攻击,创建接口 10 请求/分钟;大规模任务可开 Modal 丢到 serverless 容器。端点详情页可以看完整指纹、触发重打分、进 Attack 面板跑攻击,结果实时流回。
八、用之前要知道
- 授权边界:官方警告明确只用于授权测试,扫描和攻击都会向目标发真实请求。
- 误报:评分与攻击判定全是启发式,列表里的「高危」不等于真实漏洞。
- 成本:Shodan API 按查询计费,代码每页结果自觉间隔 1 秒限速,32 条查询全跑一遍的配额要自己算。
- 运维:MongoDB + Redis + Nuclei + 前端,是个小平台不是单条命令。
- 32 条 Shodan 查询,11 类协议;README 表只列了 30 行
- 评分:无鉴权 +4.0 为最大单因子;critical ≥9.0;危险组合 4 种
- MCP 引擎 7 阶段:侦察 → 未鉴权调用 → 文件读取 → 命令执行 → SSRF → 提示注入 → 数据库提取
- 深度 4 档(quick/standard/deep/exhaustive),默认 standard、20 步上限
- 并发:3 扫描 / 5 攻击 / 创建接口 10 请求每分钟
- AI 状态:ANTHROPIC_API_KEY 只有声明没有调用,Claude 攻击推理在 ROADMAP
- 资料:仓库 · 发现引擎文档 · Nuclei 模板