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

?? MCP生態

Supabase MCP插件SQL注入漏洞復盤:Server端權限校驗與工具注冊安全開發實踐

發布時間:2026-04-16 分類: MCP生態
摘要:Supabase MCP插件漏洞復盤:Server端安全開發要點漏洞真實影響:不是“可能”,是已發生的數據泄露Supabase MCP插件的漏洞已在生產環境被利用。攻擊者通過構造/mcp/tools路徑下的惡意請求,繞過所有權限檢查,直接執行任意SQL查詢——包括SELECT * FROM auth.users、pg_dump導出語句等。有團隊確認其PostgreSQL日志中出現未授權的CO...

封面

Supabase MCP插件漏洞復盤:Server端安全開發要點

漏洞真實影響:不是“可能”,是已發生的數據泄露

Supabase MCP插件的漏洞已在生產環境被利用。攻擊者通過構造/mcp/tools路徑下的惡意請求,繞過所有權限檢查,直接執行任意SQL查詢——包括SELECT * FROM auth.userspg_dump導出語句等。有團隊確認其PostgreSQL日志中出現未授權的COPY ... TO PROGRAM調用,說明攻擊者已獲取數據庫文件系統訪問權限。

這不是理論風險。它暴露了一個關鍵事實:MCP Server實現中,工具注冊邏輯與權限校驗完全解耦。

問題根源:兩處硬傷

1. 工具調用零校驗

MCP規范要求Server對每個工具調用做三重檢查:調用方身份、工具白名單、參數合法性。但Supabase插件只做了第一項(JWT解析),且未驗證token中聲明的scope是否包含該工具權限。

更嚴重的是,它把工具函數直接掛載到HTTP路由,例如:

# 錯誤示范:工具函數直連路由
@app.route('/mcp/tools/query', methods=['POST'])
def query_tool():
    # 這里沒有檢查調用方是否有query權限
    return execute_sql(request.json['query'])  # ← 直接執行用戶輸入

結果是:任何持有有效JWT(哪怕只是anon角色)的請求,都能觸發任意SQL。

2. Agent調用鏈無邊界控制

MCP協議允許Agent間相互調用,但Supabase插件未限制調用深度和目標范圍。攻擊者發現:

  • Agent A(低權限)可調用Agent B(高權限)
  • Agent B在執行時未校驗調用來源,直接信任傳入參數
  • 最終形成跳板:anon → data_cleaner → model_inference → db_admin

日志顯示,一次攻擊鏈包含7次跨Agent調用,其中3個Agent運行在相同進程內,共享內存空間——權限隔離徹底失效。

實操方案:現在就能加上的防護

權限校驗必須嵌入工具層

不要依賴中間件統一鑒權。每個工具函數啟動時,必須顯式檢查:

  • 調用方JWT中的scope字段是否包含當前工具ID
  • 請求參數是否在預定義schema內(用Pydantic或JSON Schema)
  • 數據庫操作是否限定在租戶schema下(如tenant_123.users而非public.users
from pydantic import BaseModel, Field
from typing import Literal

class QueryToolInput(BaseModel):
    query: str = Field(..., max_length=2048)
    mode: Literal["read", "explain"] = "read"  # 禁止write/delete

@app.route('/mcp/tools/query', methods=['POST'])
@token_required
def query_tool():
    try:
        input_data = QueryToolInput.model_validate(request.json)
    except Exception as e:
        return jsonify({"error": "Invalid input"}), 400
    
    # 關鍵:從token提取租戶ID和權限
    token_payload = jwt.decode(
        request.headers['Authorization'], 
        key=SECRET_KEY, 
        algorithms=["HS256"]
    )
    
    if "query" not in token_payload.get("scope", []):
        return jsonify({"error": "Permission denied"}), 403
    
    # 強制重寫SQL前綴
    safe_query = f"SET search_path TO tenant_{token_payload['tenant_id']}; {input_data.query}"
    
    # 攔截危險操作
    if any(kw in safe_query.lower() for kw in ["drop", "delete", "copy", "create"]):
        return jsonify({"error": "Write operations forbidden"}), 403
    
    return jsonify(execute_sql(safe_query))

Agent調用必須帶簽名和超時

禁止裸HTTP調用。所有Agent間通信需滿足:

  • 調用方用私鑰對請求體簽名,接收方用公鑰驗簽
  • 每次調用附帶caller_idttl(建議≤5秒)
  • 接收方拒絕ttl過期或caller_id不在白名單的請求
import hmac
import time
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key

def verify_agent_call(payload: dict, signature: str, public_key_pem: str) -> bool:
    # 驗證簽名
    pub_key = load_pem_public_key(public_key_pem.encode())
    try:
        pub_key.verify(
            bytes.fromhex(signature),
            payload['body'].encode(),
            padding.PKCS1v15(),
            hashes.SHA256()
        )
    except Exception:
        return False
    
    # 驗證時效性
    if time.time() - payload['timestamp'] > 5:
        return False
    
    # 驗證調用方白名單
    if payload['caller_id'] not in ALLOWED_AGENTS:
        return False
    
    return True

@app.route('/api/call_agent', methods=['POST'])
def call_agent():
    data = request.json
    if not verify_agent_call(
        data, 
        request.headers.get('X-Signature'), 
        AGENT_PUBLIC_KEYS[data['target_id']]
    ):
        return jsonify({"error": "Invalid call"}), 403
    
    # 執行調用...

安全不是功能,是部署約束

合規Agent的變現能力,取決于它能否通過以下硬性檢查:

  • 租戶隔離:每個請求必須綁定tenant_id,數據庫連接池按租戶分隔
  • 資源熔斷:單次工具調用CPU時間>2s或內存>100MB時強制終止
  • 審計留痕:所有工具調用記錄caller_idtool_idinput_hashduration_ms到獨立審計表

沒有這些,所謂“安全增值服務”只是營銷話術。用戶真正付費的,是能寫進SLA的確定性保障——比如“SQL注入防護覆蓋率100%”、“跨租戶數據泄露零事件”。

立即行動清單

  1. 檢查你的MCP Server:搜索代碼中所有@app.route裝飾器,確認每個工具路由是否包含scope校驗和參數schema驗證
  2. 禁用危險工具:臨時移除execute_sqlrun_shell等高危工具,改用預編譯查詢模板
  3. 強制租戶上下文:在所有數據庫操作前插入SET search_path TO tenant_xxx,并在連接池初始化時綁定
  4. 添加調用簽名:為Agent間通信生成RSA密鑰對,要求所有/api/call_agent請求攜帶X-Signature

別等下一個漏洞。現在就打開編輯器,刪掉那行沒校驗scope的return execute_sql()

返回首頁