目的与范围
本文档提供了Model Context Protocol (MCP) 的安全考虑, 补充了MCP授权规范。本文档识别了特定于MCP实现的安全风险、攻击途径和最佳实践。
本文档的主要受众包括实施 MCP 认证流程的开发人员、MCP 服务器操作人员以及评估基于 MCP 系统的安全专业人士。应结合 MCP 认证规范与OAuth 2.0 安全最佳实践一同阅读本文档。
本节详细介绍了针对MCP实现进行的攻击,以及潜在的防御措施。
混乱代表问题
攻击者可以利用代理其他资源服务器的MCP服务器,制造“confused deputy”漏洞。
MCP 代理服务器
: 一个连接MCP客户端与第三方API的MCP服务器,提供MCP功能的同时将操作委托给第三方API服务器,并作为单一的OAuth客户端。
第三方授权服务器
: 保护第三方API的授权服务器。它可能缺少动态客户端注册支持,要求MCP代理对所有请求使用静态客户端ID。
第三方API
: 提供实际API功能的受保护资源服务器。访问此API需要由第三方授权服务器发放的令牌。
静态客户端ID强>
: MCP代理服务器与第三方授权服务器通信时使用的固定OAuth 2.0客户端标识符。此客户端ID指的是MCP服务器作为第三方API的客户端。
无论由哪个MCP客户端发起请求,所有MCP服务器与第三方API交互时该值都保持一致。
架构与攻击流程
标准 OAuth 代理使用方式(保留用户同意授权状态)
恶意OAuth代理使用(跳过用户授权)
攻击描述
当MCP代理服务器使用静态客户端ID与不支持动态客户端注册的第三方授权服务器进行身份验证时,以下攻击变得可能:
- 用户通过MCP代理服务器正常认证以访问第三方API
- 在此流程中,第三方授权服务器会在用户代理(user agent)上设置一个cookie,表示对静态客户端ID的同意
- 攻击者随后向用户发送一条恶意链接,包含了一个精心构造的授权请求,该请求携带了一个恶意重定向URI以及一个新近动态注册的客户端ID
- 当用户点击链接时,其浏览器仍保留着先前合法请求中的同意cookie
- 第三方授权服务器检测到cookie并跳过许可屏幕
- MCP授权代码被重定向到攻击者的服务器(在动态客户端注册期间通过伪造的redirect_uri指定)
- 攻击者在没有用户明确批准的情况下,使用窃取的授权码交换 MCP 服务器的访问令牌
- 攻击者现在可以以受陷用户的身份访问第三方API
缓解措施
使用静态客户端ID的MCP代理服务器必须在为每个动态注册的客户端转发到第三方授权服务器之前获取用户同意(可能需要另外的同意)。
令牌透传
“令牌透传”是一种反模式,其中MCP服务器接受来自MCP客户端的令牌,而没有验证这些令牌是否已正确签发给MCP服务器,并将其"透传"给下游API。
令牌透传在授权规范中被明确禁止,因为它引入了一系列安全风险,包括:
- 安全控制规避
- MCP服务器或下游API可能实现了重要的安全控制措施,如速率限制、请求验证或流量监控,这些措施依赖于令牌受众或其他凭据约束。如果客户端能够直接获取并使用令牌与下游API交互,而无需MCP服务器进行适当验证或确保令牌是针对正确服务颁发的,那么他们将绕过这些控制措施。
- 问责和审计追踪问题
- 当客户端使用上游颁发的访问令牌调用时,MCP服务器将无法识别或区分MCP客户端,该令牌可能对MCP服务器不透明。
- 下游资源服务器的日志可能显示的请求看起来来源于一个不同的身份和不同的源,而不是实际转发令牌的的 MCP 服务器。
- 这两个因素都使事件调查、控制和审计变得更加困难。
- 如果MCP Server传递令牌时未验证其声明(例如角色、权限或受众)或其他元数据,持有被盗令牌的恶意行为者可以利用服务器作为数据渗漏的代理。
- 信任边界问题
- 下游资源服务器对特定实体授予信任。这种信任可能包含对来源或客户端行为模式的假设。打破这种信任边界可能导致意外问题。
- 如果令牌在未经适当验证的情况下被多个服务接受,攻击者通过入侵一个服务可以利用该令牌访问其他连接的服务。
- 未来兼容性风险
- 即使今天某个MCP服务器以“纯代理”的身份启动,未来可能仍需添加安全控制。从正确的令牌受众分离开始,有助于更轻松地演进安全模型。
缓解措施
MCP servers 不可接受任何未明确为MCP服务器颁发的令牌。
会话劫持
Session hijacking 是一种攻击向量,其中服务器向客户端提供一个会话ID,而未经授权的一方能够获取并使用相同的会话ID来冒充原始客户端,并代表其执行未经授权的操作。
会话劫持提示注入
会话劫持冒充
攻击描述
当您拥有多个处理MCP请求的有状态HTTP服务器时,可能存在以下攻击向量:
会话劫持式提示注入
-
客户端连接到 Server A 并获得一个会话ID。
-
攻击者获取现有的会话ID并发送一个恶意事件到服务器B,附带该会话ID。
- 当服务器支持redelivery/resumable streams时,在接收响应前故意终止请求可能导致它通过服务器发送事件的GET请求被原始客户端恢复。
- 如果特定服务器因工具调用(例如
notifications/tools/list_changed)而触发服务器发送事件,这种情况可能影响服务器提供的工具,最终客户端可能获得其未知已启用的工具。
-
服务器B将事件(关联会话ID)加入共享队列。
-
服务器A 使用会话ID轮询队列以获取事件,并获取恶意载荷。
-
服务器A 将恶意载荷作为异步或恢复的响应发送给客户端。
-
客户端接收恶意有效载荷并执行,可能导致系统被侵入。
会话劫持模拟
- MCP客户端向MCP服务器进行身份验证,创建一个持久性会话ID。
- 攻击者获取会话ID。
- 攻击者使用会话ID向MCP服务器发起调用。
- MCP服务器不进行额外的授权检查,会将攻击者视为合法用户,从而允许未经授权的访问或操作。
缓解措施
为防止会话劫持和事件注入攻击,应实施以下防护措施:
实现授权功能的MCP服务器必须验证所有入站请求。
MCP服务器不可使用会话来验证身份。
MCP 服务器 必须 使用安全、非确定性的会话 ID。
生成的会话 ID(例如,UUID) 应当 使用安全的随机数生成器。避免可预测或顺序的会话标识符被攻击者猜到。轮换或使会话 ID 过期也可以降低风险。
MCP servers 应当 将会话ID绑定到用户特定信息。当存储或传输会话相关数据时(例如在队列中),将会话ID与授权用户的唯一信息结合,例如其内部用户ID。使用类似 : 的键格式。这确保了即便攻击者猜中了一个会话ID,也无法冒充其他用户,因为用户ID是从用户令牌派生而非由客户端提供。
MCP服务器可选择性地利用额外的唯一标识符。