揭示 Claude Code、Gemini CLI 等工具的 MCP 认证缺陷可被利用执行任意代码,所有使用这类工具的程序员需立即关注。
在我们的安全测试中,我们发现通过 Claude Code 和 Gemini CLI 等常见编码工具连接到恶意的 MCP 服务器,可能会让攻击者即时获得对用户计算机的控制权。
作为预览,这里是我们通过 Claude Code 在某人的计算机上打开计算器("弹出calc")的视频:
"弹出 calc" 是展示远程代码执行的一种无害方式。我们发现的漏洞可以扩展到更恶意的目的,例如无形地安装反向 shell 或恶意软件。
今年早些时候,MCP 推出了 OAuth 标准来认证客户端。许多 MCP 客户端没有验证恶意 MCP 服务器传递的授权 URL。我们能够利用这个漏洞在流行的工具中实现远程代码执行(RCE)。
在 Veria Labs,我们构建 AI agent,为高风险行业提供安全保障,让你可以快速自信地发货。由美国排名第一的竞技黑客队的成员创办,我们已经在 AI 工具、操作系统和数十亿美元的加密交易所中发现了严重漏洞。
认为我们能帮助保护你的系统吗?我们很乐意聊天!在这里预约通话。
MCP(Model Context Protocol,模型上下文协议)允许 AI 连接外部工具、API 和数据源。它通过共享上下文和执行操作来扩展 LLM 应用的基础能力,例如为 Gemini 提供 Google Drive 访问权限。
在 3 月,Anthropic 发布了首个 MCP 规范修订版,引入了使用 OAuth 的授权框架。OAuth 是驱动"用 Google 登录"和其他类似认证方法的标准。将 OAuth 添加到 MCP 是对 AI 生态的巨大改进,为 MCP 服务器和客户端提供了标准化的认证方式。
然而,MCP 客户端实现 OAuth 的方式创造了一个新的且微妙的攻击面。在这篇博文中,我们以不同程度的成功利用这个攻击面,针对包括 Cloudflare 的 use-mcp 客户端库、Anthropic 的 MCP Inspector、Claude Code、Gemini CLI 以及(几乎)ChatGPT 本身的不同应用。
核心问题很简单:MCP 服务器控制客户端将用户重定向到哪里进行认证,而大多数客户端完全信任了这个 URL。
我们最初在 6 月发现了这个漏洞模式,当时 Cloudflare 发布了他们的 use-mcp 库。在撰写本文时,该库在 npm 上有超过 36,000 次每周下载。
该漏洞出现在 OAuth 流程中,服务器告诉客户端在哪里打开浏览器窗口进行身份验证。漏洞出现在 src/auth/browser-provider.ts 中。代码如下:
如果你熟悉 web 渗透测试,你可能已经看出问题所在了。
use-mcp 客户端在 authUrlString 上执行 window.open(),而 authUrlString 是 MCP 服务器直接提供给客户端的任意字符串。这创建了 XSS 漏洞,因为你可以在 authUrlString 中提供 javascript: URL。当提供给 window.open 时,javascript: URL 会在当前加载的页面上执行作为 JavaScript 代码提供的所有内容。
影响:连接到具有 use-mcp 库的 MCP 应用的用户容易受到服务器传递任意 JavaScript 的攻击,客户端将自动在用户的浏览器上执行。这可能导致劫持用户会话和接管该网站的用户账户。
我们对 cloudflare/remote-mcp-github-oauth 使用了以下 Cloudflare Workers 示例代码作为我们的概念验证(PoC)。这使设置过程变得简单,PoC 只需要我们修改几行代码。
具体来说,我们的恶意 authUrlString 有效负载如下:
我们能够在 Cloudflare 的 Workers AI LLM Playground 上演示我们的 PoC:
新打开的窗口被视为同源,允许我们通过 window.opener 劫持原始网页。这给了我们对父窗口的 JavaScript 上下文的引用。
由于我们可以强制执行任意客户端 JavaScript,任何通过 use-mcp 库连接到 MCP 服务器的用户都可能容易受到会话劫持和账户接管等漏洞的影响。
在处理我们的漏洞利用时,我们使用 Anthropic 的 MCP Inspector 来调试我们的恶意 MCP 服务器。在用 MCP Inspector 进行一些实验时,我们发现它也容易受到与 Cloudflare 的 use-mcp 库相同的漏洞!
我们现在有了 XSS,但这不允许我们做太多事情。然而,由于该应用在用户机器上本地运行,我们有兴趣看看是否可以做得更多。事实证明,我们可以。我们可以使用 MCP Inspector 的 stdio 传输请求连接,以将此 XSS 升级到用户系统上的远程代码执行(RCE)。
在 MCP Inspector 的环境中,浏览器 UI 不能直接与本地进程交谈,因此 Inspector Proxy(在你的机器上运行的小型 Node.js 服务)充当中间人。当 UI 要求通过 stdio 连接到服务器时,代理将请求的命令生成为子进程,并在浏览器和该进程之间桥接消息。在功能上,它是:
该桥接角色将检查器 UI 中的 XSS 转变为 RCE:如果攻击者控制的 JavaScript 可以在浏览器 UI 中运行并获取代理的认证令牌,它可以告诉代理生成任何本地命令,有效地将 XSS 升级为主机上的任意代码执行。
stdio 传输通常用仅 MCP Inspector 客户端知道的认证令牌来保护其他本地进程。然而,由于我们有 XSS,我们可以从查询参数 MCP_PROXY_AUTH_TOKEN 窃取此令牌。
这给了我们对用户系统的完全远程代码执行,权限为 MCP Inspector 进程的权限。请注意,虽然此特定漏洞利用是为 Windows 编写的,但 Linux 和 Mac 系统也容易受到攻击。
我们还决定检查我们最喜欢的命令行 agentic 代码编辑器是否可能容易受到攻击,因为它们是 MCP 实现最受欢迎的一些程序。
Claude Code 不是开源的,但其 npm 包包含了一个缩小的包。我们能够在 socket.dev 上浏览不同版本以获取 cli.js,其中包含单个文件中的整个 Claude Code CLI。
相关代码(为清晰起见已修改)如下:
虽然它执行了 URL 模式验证——起初似乎是安全的——Windows 特定的代码仍然容易受到命令注入的影响。它使用 cmd.exe /c start <authUrl> 生成浏览器,但我们可以追加 &calc.exe,导致 cmd.exe 启动额外的程序:cmd.exe /c start <authUrl>&calc.exe。
因此,这是我们的有效负载:
Claude Code 版本 1.0.54 将其重写为使用 PowerShell 而不是 cmd.exe。
我们改编了我们的漏洞利用以使用 PowerShell 的字符串插值功能。双引号 PowerShell 字符串允许在构造字符串时计算表达式,类似于 JavaScript 模板文字:
此有效负载将 calc.exe 编码为 base64,然后在字符串构造期间使用 PowerShell 的表达式计算来解码并执行它。
Gemini CLI 以完全相同的方式容易受到攻击。它将 OAuth URL 传递给流行的 open npm 包。
open 包的 README 包含这个警告:
This package does not make any security guarantees. If you pass in untrusted input, it's up to you to properly sanitize it.
事实证明,open README 中的警告是有充分理由的。查看 open 的源代码,我们可以看到 URL 打开逻辑也通过 PowerShell 实现,具有使 Claude Code 容易受到命令注入的相同模板使用。
这意味着我们为 Claude Code 使用的完全相同的有效负载也适用于 Gemini CLI!
最近,OpenAI 推出了提供完整 MCP 支持的 ChatGPT 开发者模式,能够向 ChatGPT 添加自定义 MCP 连接器。
查看 ChatGPT 的客户端 JavaScript,我们看到 ChatGPT 在 OAuth 流程中直接将修改的重定向 URL 传递给 window.open。这与 use-mcp 包非常相似,导致了几乎相同的漏洞利用。
然而,存在强大的内容安全策略(CSP)防止 javascript: URL 的执行。我们尝试使用具有 text/html mimetype 的自定义 data URL 进行漏洞利用,但这也被 ChatGPT 的 CSP 阻止了。
对于在 Claude web 应用上添加的连接器,我们观察到将使用恶意 URL(由 MCP 服务器指定)执行服务器端重定向。然而,JavaScript 执行没有发生。这是因为 javascript: URL 不会从服务器端重定向执行。
受影响供应商的响应很迅速;但他们采取了不同的方法来解决潜在问题:
Cloudflare 创建了 strict-url-sanitise 包,它验证 URL 方案并阻止 javascript: URL。这通过输入验证解决了特定的攻击向量。
Anthropic 对 Claude Code 的修复经历了多次迭代,最终决定通过 await execFileAsync("rundll32",["url,OpenURL",url],{}) 完全消除 shell 使用。由于他们已经有 URL 模式验证,这完全消除了攻击面。
Google 放弃了容易受到攻击的 open 包,并自己重新实现了 URL 打开。在他们的修复 PR 中,他们通过为 PowerShell 转义单引号(' 到 '')来清理 URL。这有效,但不是一个非常稳健的修复。
最大的影响来自 Anthropic 对 MCP TypeScript SDK 的更新,该更新将 javascript: 等危险 URI 方案加入黑名单。由于包括 MCP Inspector 在内的多个工具使用此 SDK,此单一上游更改立即改善了整个生态系统的安全性。
无法在 ChatGPT 上实现 XSS 表明传统的深度防御方法仍然有效。虽然底层系统容易受到攻击,但 CSP 防止了我们将其升级为高严重性漏洞。AI 空间中的许多内容都建立在现有 web 技术之上,可以从利用 web 安全功能中受益。
像 Anthropic 的 MCP TypeScript SDK 所做的那样的广泛的上游改进使生态系统整体更加安全。漏洞利用在某些地方太容易了,但轨迹令人鼓舞,我们对 AI 安全的未来充满希望。
我们要感谢以下漏洞赏金计划:
他们有快速的补丁流程,Claude Code 和 Gemini CLI 都包含自动更新程序,允许修复快速部署。
Cloudflare:
Anthropic(Claude Code):
Anthropic(MCP Inspector):
Google(Gemini CLI):
注意:与 HackerOne 不同,Google VRP 在决定赏金的同时检查重复项。
Cherry Studio 曾短暂容易受到攻击,但在发现漏洞时,我们找不到合适的安全联系。后来使用 Cloudflare 使用的同一个包(strict-url-sanitise)创建了一个补丁。
Gemini CLI 漏洞曾短暂影响下游分支 Qwen Code。一旦上游修复发布,Qwen Code 团队迅速修补了他们的分支。
open 漏洞并非新发现。它以前被用来利用 npm 上的 mcp-remote 包。
每个 PoC 都基于相同的代码,针对每个目标有微小调整。代码发布在 https://github.com/verialabs/mcp-auth-exploit-pocs,包括展示漏洞利用的额外视频。