国产日韩欧美-97在线观看免费-亚洲欧洲日韩-亚洲free性xxxx护士白浆-国产精品网站在线观看-日韩有码一区-日本大片在线观看-欧美精品一区二区性色a+v-97在线精品-亚洲久草视频-天天操人人爽-你懂的国产精品-国产国语对白-就去干成人网-亚洲美女色视频

?? MCP生態

MCP協議安全邊界缺陷分析與Supabase漏洞加固指南

發布時間:2026-04-17 分類: MCP生態
摘要:MCP協議安全邊界缺陷解析與加固指南:Supabase漏洞啟示錄Supabase漏洞暴露了什么Hacker News上熱議的“Supabase MCP漏洞致全庫SQL裸奔導出”事件,本質不是Supabase寫錯了代碼,而是MCP Server在默認配置下把數據庫當成了公共讀取器——任何能通過基礎認證的用戶,都能直接觸發/export端點,拿到整個PostgreSQL實例的SQL dump。這...

封面

MCP協議安全邊界缺陷解析與加固指南:Supabase漏洞啟示錄

Supabase漏洞暴露了什么

Hacker News上熱議的“Supabase MCP漏洞致全庫SQL裸奔導出”事件,本質不是Supabase寫錯了代碼,而是MCP Server在默認配置下把數據庫當成了公共讀取器——任何能通過基礎認證的用戶,都能直接觸發/export端點,拿到整個PostgreSQL實例的SQL dump。

這個漏洞不依賴SQL注入、不靠服務端模板渲染,純粹是權限模型在協議層塌方的結果。它提醒我們:當AI Agent能自由調用MCP Server時,協議本身必須守住第一道門,而不是把所有信任都押在應用層的if語句上。

安全邊界在哪塌了

1. 默認配置等于開放大門

MCP Server啟動時不強制要求聲明資源策略。它的默認行為是:只要JWT簽名有效,就放行所有GET /resources/*POST /actions/*請求。這不是疏忽,是協議設計選擇——但這個選擇在多租戶場景下立刻失效。

  • 權限粒度缺失:MCP規范里沒有resource_id、operation_type、context_scope等字段的強制校驗邏輯。Server實現通常只校驗sub(用戶ID)和exp(過期時間),剩下的全交給上層應用。
  • 認證 ≠ 授權:Server完成身份認證后,直接把原始請求轉發給后端處理函數。如果那個函數沒做二次鑒權,或者鑒權邏輯被繞過(比如傳入resource_id=*table_name=public.*),數據就裸奔了。

Supabase案例中,攻擊者發送的請求類似:

POST /v1/export HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{"format": "sql", "schema": "public", "tables": ["*"]}

MCP Server驗證完JWT就轉發,而Supabase的導出Handler沒對tables字段做白名單過濾,也沒檢查當前用戶是否有pg_dump權限。

2. 協議層零鑒權邏輯

MCP協議文檔明確將“授權決策”劃歸應用層責任。這導致兩個現實問題:

  • 鑒權邏輯分散:同一個資源可能在API網關、MCP Server中間件、業務Handler里被校驗三次,也可能一次都沒被校驗——取決于開發者當天的心情。
  • 請求可篡改無感知:MCP不強制簽名請求體,也不校驗Content-MD5X-Signature頭。攻擊者能輕松修改user_id、tenant_idscope等關鍵參數,而Server照單轉發。

三步堵住協議層缺口

1. 在MCP Server層做鑒權,別甩鍋給應用

RBAC必須下沉到協議入口。不是加個中間件,而是讓MCP Server在解析完JWT后,立即查策略引擎,決定是否允許本次請求抵達業務Handler。

# mcp_server/middleware/authz.py
from policy_engine import evaluate

def enforce_mcp_authz(jwt_payload, method, path, body):
    # 提取策略上下文
    context = {
        "user_id": jwt_payload["sub"],
        "role": jwt_payload.get("role", "user"),
        "method": method,
        "path": path,
        "resource": extract_resource_from_path(path),
        "action": infer_action_from_method_and_path(method, path),
        "body_keys": list(body.keys()) if isinstance(body, dict) else []
    }
    
    # 同步調用策略引擎(不走網絡,本地加載OPA/WASM)
    if not evaluate("mcp_authz.rego", context):
        raise PermissionDenied(f"Policy denied for {context}")

# 在請求路由前調用
@app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE"])
def handle_mcp_request(path):
    jwt = parse_jwt(request.headers.get("Authorization"))
    body = request.get_json() or {}
    enforce_mcp_authz(jwt, request.method, path, body)
    return dispatch_to_handler(path, body)

2. 權限控制必須精確到操作+資源+上下文

“能訪問用戶表”不等于“能導出用戶表”。權限模型要區分:

  • read:user:profile(讀個人資料)
  • read:table:users(讀users表所有行)
  • export:database:public(導出整個public schema)
# 權限檢查邏輯必須嵌入業務Handler內部,而非僅依賴路由
def export_database_handler(user_id, schema, tables):
    # 檢查用戶是否有該schema的導出權限
    if not has_permission(user_id, f"export:schema:{schema}"):
        raise Forbidden("Missing export:schema permission")
    
    # 檢查每個table是否在用戶授權范圍內
    allowed_tables = get_allowed_tables(user_id, schema)
    for table in tables:
        if table != "*" and table not in allowed_tables:
            raise Forbidden(f"Table {table} not in allowed list")
    
    # 執行導出(此時已確保安全)
    return pg_dump(schema, tables)

# 權限數據存在獨立策略服務里,不和業務DB混用
def get_allowed_tables(user_id, schema):
    return requests.get(
        f"https://policy.internal/allowed-tables?user={user_id}&schema={schema}"
    ).json()

3. Agent調用必須沙箱化,且沙箱由MCP Server管理

Agent不是可信執行體。MCP Server收到/agent/run請求后,不能直接subprocess.run(),而應:

  • 啟動隔離容器(gVisor或Firecracker輕量VM)
  • 掛載只讀的代碼目錄 + 臨時內存盤
  • 設置rlimit硬限制(CPU 5s、內存 256MB、網絡禁止外連)
  • 超時強殺,返回SIGKILL狀態碼而非SIGTERM
# mcp_server/agent_runner.py
import firecracker
from tempfile import mkdtemp

def run_agent_sandboxed(agent_code, timeout=5):
    # 創建臨時工作區
    workdir = mkdtemp()
    with open(f"{workdir}/main.py", "w") as f:
        f.write(agent_code)
    
    # 啟動Firecracker microVM
    vm = firecracker.MicroVM(
        kernel="/boot/vmlinux",
        initrd="/rootfs.ext4",
        cpu_count=1,
        mem_size_mb=256,
        network="none",  # 禁止網絡
        drives=[firecracker.Drive(workdir, readonly=True)]
    )
    
    try:
        vm.start()
        result = vm.execute("python3 /mnt/main.py", timeout=timeout)
        return {"status": "success", "output": result.stdout}
    except firecracker.TimeoutError:
        vm.kill()
        return {"status": "timeout", "error": "Execution exceeded 5s"}
    finally:
        vm.cleanup()

安全是可交付的模塊,不是PPT里的形容詞

用戶不會為“高可用”付錢,但會為“導出數據前必須二次確認+審計日志+72小時追溯”付費。安全能力直接對應三個變現點:

  • 企業版強制策略引擎:把OPA策略編譯成WASM,在MCP Server內聯執行,按策略條數收費
  • 沙箱運行時即服務:按Agent調用次數和資源配額計費(如:100次/月免費,超量0.02美元/次)
  • 合規審計包:自動生成SOC2、ISO27001所需日志視圖,附帶簽名報告

這些不是附加功能,是MCP Server的默認行為開關。關掉它們?可以,但得簽免責協議。

下一步:現在就做這五件事

  1. 停用所有*通配符權限:檢查MCP Server配置,刪掉allow_all_authenticated這類flag
  2. /health端點旁加/policy-status:返回當前生效的策略版本、最后更新時間、未覆蓋路徑列表
  3. 給所有Agent調用加沙箱包裝器:哪怕只是unshare -r -f --mount-proc也比裸跑強
  4. 重寫導出類API:強制要求tables字段為非空數組,禁用["*"],改用list_tables接口分頁獲取
  5. 在CI里加策略測試:用真實JWT token跑curl -X POST /export -d '{"tables":["users"]}',斷言返回403而非200
返回首頁