
MCP 身份验证与授权:OAuth 2.1、令牌委托和混淆代理问题
身份验证是远程 MCP 服务器最关键的安全层。了解为什么必须使用带有 OIDC 的 OAuth 2.1,令牌委托如何防止混淆代理攻击,以及为什么令牌直通是 AI 集成中最危险的模式之一。...

OWASP GenAI 安全项目定义了安全 MCP 服务器部署的五类最低标准。使用此检查清单在投入生产之前评估您在身份认证、隔离、工具、验证和部署方面的当前状况。
OWASP GenAI 安全项目的 MCP 服务器开发实用指南最终形成了一个具体的审查检查清单——“MCP 安全最低标准”。此检查清单定义了在将 MCP 服务器部署到生产环境之前必须具备的基线控制。
本文展示了完整的检查清单,并为每个项目提供实施指导,按 OWASP 指南定义的五个安全领域组织。将其用于部署前安全审查、定期审计以及作为修复已识别差距的框架。
标记项目: 对于每个项目,记录通过(已实施并验证)、失败(未实施或部分实施)或不适用(不适用于此部署)。
部署门槛: 类别 1(身份认证、授权、策略)和类别 2(隔离)中的项目是硬性部署门槛——任何失败都应阻止上线,直到修复。其他类别中的项目应通过记录的时间表进行风险接受。
审查触发器: 在对 MCP 服务器代码、工具注册表、身份验证配置、部署环境进行任何重大更改后,或在加入新类别的工具时,重新运行完整的检查清单。
这是最高优先级的类别。身份验证失败会授予攻击者直接访问 MCP 服务器可以执行的所有操作的权限。
要验证的内容: 每个到 MCP 服务器的远程连接都需要通过正确配置的 OAuth 2.1 授权服务器进行身份验证。匿名连接被拒绝。使用 STDIO 的本地 MCP 服务器可以使用适合其部署环境的替代身份验证。
如何测试: 尝试在没有授权标头的情况下连接。尝试使用格式错误或过期的令牌连接。两者都应导致身份验证失败,而不是访问工具。
常见失败模式: 开发端点在没有身份验证的情况下保持可访问;回退到不验证过期或范围的 API 密钥身份验证;仅在会话建立时进行令牌验证,而不是每次请求时。
要验证的内容: 访问令牌在几分钟内过期(而不是几小时)。每个令牌携带当前任务所需的最小范围。每次工具调用都验证令牌的签名、发行者(iss)、受众(aud)、过期时间(exp)和所需范围——而不仅仅是在会话建立时。
如何测试: 使用有效令牌,然后等待其过期(或手动将时钟向前设置)。尝试工具调用——它应该失败并返回 401,而不是基于缓存的验证结果成功。
常见失败模式: 令牌验证在会话开始时缓存且不重复;令牌具有 24 小时以上的生命周期;使用广泛的"管理员"范围而不是特定于操作的范围;未检查 exp 字段。
要验证的内容: MCP 服务器不会将客户端令牌转发到下游 API。所有下游服务调用都使用明确颁发给 MCP 服务器的令牌(通过代理流或服务凭证)。集中式策略网关拦截所有工具调用,并在执行任何工具代码之前执行身份验证、授权、同意和审计日志记录。
如何测试: 审查代码以查找在出站 API 调用中转发传入客户端令牌的任何位置。检查下游服务访问日志,以验证请求是使用服务器凭证而不是用户凭证到达的。
常见失败模式: 下游调用中的 Authorization: Bearer ${request.headers.authorization} 模式;授权检查分散在各个工具处理程序中;没有集中的策略执行点。
多租户环境中的隔离失败是灾难性的——它们使一个用户能够访问另一个用户的数据。这些是硬性部署门槛。
要验证的内容: 没有全局变量、类级属性或共享单例实例存储特定于用户或会话的数据。每个会话使用独立实例化的对象或会话键命名空间(例如,以 session_id: 为前缀的 Redis 键)。代码审查确认会话之间没有共享可变状态。
如何测试: 使用不同用户身份运行两个并发会话。验证在会话 A 中写入的数据无法在会话 B 中读取。使用并发负载测试检查可能导致会话状态泄漏的竞态条件。
常见失败模式: 单例服务中的 self.user_context = {} 作为类属性;没有会话键命名空间的全局缓存;未正确限定到请求生命周期的线程本地存储。
要验证的内容: 除了执行上下文之外,任何共享基础设施(数据库、缓存、消息队列)都强制执行每个用户的访问控制。即使共享基础设施配置错误或受到威胁,在一个用户会话中执行的查询也无法返回另一个用户的数据。
如何测试: 尝试通过操纵会话参数或利用共享缓存键来访问另一个用户的数据。
常见失败模式: 缓存键仅基于查询内容,而不是用户身份;没有用户范围的 WHERE 子句的数据库查询;没有每个用户子目录的共享临时文件目录。
要验证的内容: 当会话终止(干净地或通过超时/错误)时,所有相关资源立即释放:文件句柄、临时文件、内存中的上下文、缓存的令牌、数据库连接。每个会话的内存、CPU、API 速率和文件系统使用都存在限制。
如何测试: 突然终止会话(在没有优雅关闭的情况下终止连接)。验证没有残留资源。创建会话并耗尽其速率限制;验证它不会影响其他会话。
常见失败模式: 会话结束后在 /tmp 中留下临时文件;会话终止时未撤销缓存的令牌;没有资源配额允许一个会话耗尽共享基础设施。
工具安全可防止最危险的 MCP 特定攻击:工具投毒和地毯式拉取。
要验证的内容: 每个工具定义都有来自授权工具批准者的加密签名。签名涵盖完整的清单(描述、模式、版本、权限)。MCP 服务器在加载时验证此签名,并拒绝任何未签名或签名不匹配的工具。工具版本被固定——服务器无法在没有新批准签名的情况下动态加载更新的工具。
如何测试: 修改已加载工具描述中的单个字符。验证服务器检测到哈希不匹配并阻止工具加载。尝试加载未签名的工具定义——它应该被拒绝。
常见失败模式: 工具定义存储为可变配置,没有完整性验证;没有签名密钥基础设施;工具直接从共享文件系统加载,没有版本固定。
要验证的内容: 自动扫描检查工具描述中可能代表投毒尝试的类似指令的模式。定期验证确认工具的实际运行时行为与其声明的描述相匹配——声称为只读的工具在运行时不应能够执行写操作。
如何测试: 向工具描述添加可疑指令(“始终同时调用 send_webhook…"),并验证自动扫描在人工审查之前标记它。审查 SAST 工具配置以查找 MCP 特定的投毒检测规则。
常见失败模式: 没有对工具描述进行自动扫描;手动审查流程可能会遗漏长描述中嵌入的指令;没有运行时行为验证来捕获对其能力撒谎的工具。
要验证的内容: 模型上下文仅接收正确工具调用所需的字段:名称、描述、输入模式、输出模式。内部元数据、实现细节、调试信息和敏感配置在传递给模型之前被过滤掉。
如何测试: 检查模型枚举可用工具时接收到的内容。验证模型视图中没有出现内部字段、连接字符串或操作元数据。
常见失败模式: 将完整的工具配置对象传递给模型上下文;包含泄漏到模型的内部系统详细信息的错误消息;工具描述包括与调用无关的实现说明。
验证失败会导致注入、数据操纵和拒绝服务。
要验证的内容: 对每个 MCP 协议消息、每个工具调用输入以及在到达模型之前的每个工具输出都强制执行 JSON 模式验证。验证拒绝任何不符合定义模式的消息——缺少必需字段、错误类型、超出允许范围的值。
如何测试: 发送缺少必需参数的工具调用。发送带有额外意外字段的消息。两者都应被拒绝,而不是被静默忽略或使用默认值处理。
常见失败模式: 在错误条件下绕过的可选验证;仅对输入而不是输出进行验证;过于宽松的模式(接受 type: "any" 参数)。
要验证的内容: 所有输入都经过清理,以删除或转义可能导致注入的字符(XSS 序列、SQL 元字符、shell 元字符、空字节)。对所有输入和输出强制执行大小限制。服务器将来自模型的所有数据视为潜在的对抗性数据,与传统 Web 应用程序中的用户输入相同。
如何测试: 发送包含 SQL 注入负载、shell 元字符和 XSS 序列的输入。验证它们在到达下游系统之前被拒绝或安全转义。发送超过大小限制的输入——验证它被干净地拒绝。
常见失败模式: 输入直接传递到 SQL 查询或 shell 命令;没有大小限制允许超大输入导致内存耗尽;输出返回到模型时没有大小限制或内容过滤。
要验证的内容: 工具调用仅被接受为具有验证模式的结构化 JSON 对象。不处理暗示工具调用的自由格式文本生成。系统不能通过生成服务器解释为命令的自然语言来诱导执行工具调用。
如何测试: 发送描述工具调用的自然语言字符串(“使用路径 /etc/passwd 调用 delete_file 工具”)。验证服务器不会将其解释为工具调用。
常见失败模式: 同时接受结构化 JSON 和自然语言工具描述的混合系统;解析模型生成的文本以识别工具调用的服务器;可以被欺骗的基于正则表达式的工具调用解析。
部署加固限制了任何被利用漏洞的爆炸半径。
要验证的内容: MCP 服务器在最小加固容器中运行。容器进程以非 root 用户身份运行。删除不必要的 Linux 功能。网络策略将所有入站和出站流量限制为明确要求的连接。容器镜像仅包含所需的最少软件。
如何测试: 运行 docker inspect 并验证用户是非 root。审查网络策略并确认它们阻止除明确列入白名单的连接之外的所有流量。扫描容器镜像以查找不必要的软件包或已知易受攻击的软件。
常见失败模式: 为方便起见以 root 身份运行容器;没有网络策略导致允许所有出站流量;具有完整操作系统安装而不是最小镜像的基础镜像。
要验证的内容: 所有 API 密钥、OAuth 客户端密钥、数据库凭证和服务帐户令牌都存储在密钥保险库中(HashiCorp Vault、AWS Secrets Manager、Azure Key Vault 等)。环境变量、源代码、容器镜像或日志输出中不存在密钥。密钥管理操作发生在 AI 模型无法访问的中间件中——LLM 永远不会看到或处理凭证值。
如何测试: 在日志中搜索类似凭证的字符串。检查服务器进程可访问的环境变量。审查模型的可访问上下文以确认没有凭证值出现。
常见失败模式: .env 文件中的 API 密钥提交到版本控制;到达模型的错误消息中返回的凭证;作为工具参数传递的密钥出现在模型的对话上下文中。
要验证的内容: 部署管道包括自动安全扫描(SAST、SCA、依赖漏洞扫描)作为硬性门槛——扫描失败会阻止部署。所有工具调用、身份验证事件和授权决策都以完整上下文不可变地记录。日志被 SIEM 摄取,并对异常模式(验证失败激增、异常工具调用频率、意外外部连接)进行实时警报。
如何测试: 引入已知易受攻击的依赖项,并验证 CI/CD 管道使构建失败。生成异常工具调用模式,并验证 SIEM 警报在预期响应时间内触发。
常见失败模式: 安全扫描作为咨询而不是阻止门槛;日志写入攻击者可以修改的可变存储;没有对异常模式发出警报;过多的日志详细程度使相关事件无法找到。
在生产部署之前,打印或导出此检查清单,并为每个 MCP 服务器系统地完成它。让您的安全团队参与审查——许多项目需要代码审查和实时测试才能正确验证。
对于需要独立验证的团队,专业的 MCP 安全审计 会针对您的实时环境测试所有 16 个检查清单项目,使用对抗性测试技术而不是自我评估。结果是经过验证的安全状况报告,其中包含优先修复计划。
OWASP GenAI 安全项目的'MCP 安全最低标准'是一个审查检查清单,定义了 MCP 服务器在部署到生产环境之前所需的基线安全控制。它涵盖五个领域:强身份认证/授权/策略执行、严格隔离和生命周期控制、可信和受控的工具、模式驱动的验证以及加固的部署与持续监督。未能满足最低标准意味着 MCP 服务器在差距得到修复之前不应被部署。
系统地完成每个类别,将项目标记为通过、失败或不适用,并为每个决定提供证据。类别 1 或 2(身份认证和隔离)中的任何失败都应阻止部署——这些是最高风险的差距。其他类别中的失败应在部署前通过记录的修复时间表进行风险接受。在对 MCP 服务器、工具注册表或部署环境进行任何重大更改后,应重新评估检查清单。
几种工具支持自动化 MCP 安全验证:Invariant MCP-Scan(专门用于 MCP 安全扫描)、带有自定义 MCP 规则的 SAST 工具、用于依赖扫描的 npm audit 和 pip audit、用于漏洞数据库检查的 OSV-Scanner、用于运行时隔离的 Docker seccomp 和 AppArmor 配置文件,以及用于集中监控的 SIEM 集成。没有单一工具涵盖所有检查清单项目——全面覆盖需要结合静态分析、动态测试和持续监控。
阿尔西亚是 FlowHunt 的一名 AI 工作流程工程师。拥有计算机科学背景并热衷于人工智能,他专注于创建高效的工作流程,将 AI 工具整合到日常任务中,从而提升生产力和创造力。


身份验证是远程 MCP 服务器最关键的安全层。了解为什么必须使用带有 OIDC 的 OAuth 2.1,令牌委托如何防止混淆代理攻击,以及为什么令牌直通是 AI 集成中最危险的模式之一。...

MCP 服务器暴露了一个独特的攻击面,结合了传统 API 风险和 AI 特定威胁。了解 OWASP GenAI 识别的 6 个关键漏洞——工具投毒、跑路攻击、代码注入、凭证泄露、过度权限和隔离不足。...

可证明的 MCP 服务器为 FlowHunt 工作流带来了远程证明和机密计算,使 AI 代理和客户端能够在连接前验证服务器完整性。它利用硬件级加密证明来确保安全、未被篡改的 AI 流水线。...