久久一级二级,日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕,中文字慕五区,欧美日韩精品一级,9干视频在线,一线在线不卡免费,亚洲天堂久久在线观看,亚洲天堂激情一区,丁香激情四月

?? MCP生態(tài)

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

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

封面

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

Supabase漏洞暴露了什么

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

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

安全邊界在哪塌了

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

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

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

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

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

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

MCP Server驗證完JWT就轉(zhuǎn)發(fā),而Supabase的導(dǎo)出Handler沒對tables字段做白名單過濾,也沒檢查當前用戶是否有pg_dump權(quán)限。

2. 協(xié)議層零鑒權(quán)邏輯

MCP協(xié)議文檔明確將“授權(quán)決策”劃歸應(yīng)用層責(zé)任。這導(dǎo)致兩個現(xiàn)實問題:

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

三步堵住協(xié)議層缺口

1. 在MCP Server層做鑒權(quán),別甩鍋給應(yīng)用

RBAC必須下沉到協(xié)議入口。不是加個中間件,而是讓MCP Server在解析完JWT后,立即查策略引擎,決定是否允許本次請求抵達業(yè)務(wù)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 []
    }
    
    # 同步調(diào)用策略引擎(不走網(wǎng)絡(luò),本地加載OPA/WASM)
    if not evaluate("mcp_authz.rego", context):
        raise PermissionDenied(f"Policy denied for {context}")

# 在請求路由前調(diào)用
@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. 權(quán)限控制必須精確到操作+資源+上下文

“能訪問用戶表”不等于“能導(dǎo)出用戶表”。權(quán)限模型要區(qū)分:

  • read:user:profile(讀個人資料)
  • read:table:users(讀users表所有行)
  • export:database:public(導(dǎo)出整個public schema)
# 權(quán)限檢查邏輯必須嵌入業(yè)務(wù)Handler內(nèi)部,而非僅依賴路由
def export_database_handler(user_id, schema, tables):
    # 檢查用戶是否有該schema的導(dǎo)出權(quán)限
    if not has_permission(user_id, f"export:schema:{schema}"):
        raise Forbidden("Missing export:schema permission")
    
    # 檢查每個table是否在用戶授權(quán)范圍內(nèi)
    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")
    
    # 執(zhí)行導(dǎo)出(此時已確保安全)
    return pg_dump(schema, tables)

# 權(quán)限數(shù)據(jù)存在獨立策略服務(wù)里,不和業(yè)務(wù)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調(diào)用必須沙箱化,且沙箱由MCP Server管理

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

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

def run_agent_sandboxed(agent_code, timeout=5):
    # 創(chuàng)建臨時工作區(qū)
    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",  # 禁止網(wǎng)絡(luò)
        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里的形容詞

用戶不會為“高可用”付錢,但會為“導(dǎo)出數(shù)據(jù)前必須二次確認+審計日志+72小時追溯”付費。安全能力直接對應(yīng)三個變現(xiàn)點:

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

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

下一步:現(xiàn)在就做這五件事

  1. 停用所有*通配符權(quán)限:檢查MCP Server配置,刪掉allow_all_authenticated這類flag
  2. /health端點旁加/policy-status:返回當前生效的策略版本、最后更新時間、未覆蓋路徑列表
  3. 給所有Agent調(diào)用加沙箱包裝器:哪怕只是unshare -r -f --mount-proc也比裸跑強
  4. 重寫導(dǎo)出類API:強制要求tables字段為非空數(shù)組,禁用["*"],改用list_tables接口分頁獲取
  5. 在CI里加策略測試:用真實JWT token跑curl -X POST /export -d '{"tables":["users"]}',斷言返回403而非200
返回首頁
苍山县| 武邑县| 汉沽区| 宁安市| 舟曲县| 江都市| 福泉市| 大名县| 光泽县| 东莞市| 安国市| 珲春市| 德令哈市| 桐庐县| 广州市| 克拉玛依市| 江口县| 玉树县| 句容市| 靖江市| 利辛县| 明溪县| 苍山县| 南阳市| 娄底市| 布拖县| 聂荣县| 三穗县| 周至县| 大渡口区| 时尚| 乌兰察布市| 曲阜市| 武汉市| 磐安县| 南皮县| 东丽区| 安龙县| 高台县| 汉阴县| 麻栗坡县|