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

?? MCP生態

Supabase MCP權限繞過漏洞分析與安全加固實踐

發布時間:2026-04-16 分類: MCP生態
摘要:Supabase MCP漏洞實錄:權限繞過與加固實踐漏洞現場:全庫SQL導出是怎么發生的Hacker News上那條“Supabase MCP Server裸奔導出全庫SQL”的帖子不是危言聳聽。真實情況是:攻擊者發一個特制的RPC請求,繞過所有權限檢查,直接拿到pg_catalog里所有表結構、索引、視圖定義,再拼出SELECT * FROM ...語句批量執行——整個數據庫的SQL sc...

封面

Supabase MCP漏洞實錄:權限繞過與加固實踐

漏洞現場:全庫SQL導出是怎么發生的

Hacker News上那條“Supabase MCP Server裸奔導出全庫SQL”的帖子不是危言聳聽。真實情況是:攻擊者發一個特制的RPC請求,繞過所有權限檢查,直接拿到pg_catalog里所有表結構、索引、視圖定義,再拼出SELECT * FROM ...語句批量執行——整個數據庫的SQL schema和數據就這么流出去了。

這不是協議缺陷,是Supabase的MCP Server實現漏掉了關鍵校驗點。

權限校驗在哪斷了鏈

問題出在元數據接口的處理邏輯里。MCP規范要求每個RPC調用必須經過三道關卡:

  • 調用者身份可信(JWT簽名有效)
  • 請求操作在授權范圍內(如read:tables
  • 目標資源屬于該調用者可訪問的租戶/項目(租戶隔離)

但Supabase的list_tablesget_table_schema這兩個接口跳過了第二、第三步。只要能連上Server,任何未認證或低權限用戶都能調用它們。

結果就是:一個本該只讀自己表的前端Agent,能查出整個PostgreSQL實例里所有數據庫的全部表結構。

這不是MCP的鍋,是實現沒守規矩

MCP協議本身有明確的權限模型:每個RPC方法必須聲明所需權限(required_permissions: ["read:tables"]),Server必須在執行前校驗。沙箱機制也規定了Agent默認無權訪問pg_catalog、無法跨數據庫查詢。

這次被“撞穿”的不是協議邊界,而是開發者把協議當擺設——寫了RPC handler,卻忘了加if !ctx.HasPermission("read:tables") { return err }

MCP安全機制:就兩件事,別搞復雜

MCP的安全不靠玄學,靠兩根柱子:權限控制和沙箱隔離。其他都是這兩根柱子的延伸。

權限控制:每個RPC入口必須校驗

MCP的權限是動詞+名詞組合:read:tableswrite:rowsexec:sql。不是角色RBAC,是操作級ABAC。

關鍵規則:

  • 每個注冊的RPC handler開頭必須做權限檢查
  • 權限檢查必須包含租戶上下文(ctx.TenantID())和資源路徑(req.Param("table_name")
  • 拒絕時返回標準錯誤mcp.ErrPermissionDenied,不暴露拒絕原因
server.Register("query", func(ctx mcp.Context, req mcp.Request) (mcp.Response, error) {
    table := req.Param("table")
    // 必須同時校驗:權限 + 租戶歸屬 + 表白名單
    if !ctx.HasPermission("read:rows") ||
       ctx.TenantID() != getTableTenant(table) ||
       !isAllowedTable(table) {
        return nil, mcp.ErrPermissionDenied
    }
    // ...
})

沙箱隔離:資源訪問必須顯式授權

MCP沙箱不是Docker容器,是運行時約束:

  • Agent進程默認無文件系統訪問權限(os.Open直接panic)
  • 網絡只能連預注冊的endpoint(如supabase.com:5432
  • 數據庫連接自動注入租戶schema前綴(tenant_123.users

違反規則的代碼會當場失敗:

// ? 這行會panic:未授權的文件訪問
data, _ := os.ReadFile("/etc/passwd")

// ? 正確方式:通過MCP提供的安全API
content, err := ctx.ReadFile("config.yaml") // 僅限Agent工作目錄

Supabase漏洞復盤:兩個硬傷

Supabase的修復補丁(v1.23.1)暴露了最初的問題根源:

1. 元數據接口完全裸奔

list_schemasget_column_info這些方法注冊時沒聲明任何權限要求:

// 錯誤示例(原始代碼)
server.Register("list_schemas", listSchemasHandler) // 沒配required_permissions

導致MCP Server的全局權限中間件直接跳過校驗。

2. 沙箱配置被手動繞過

為支持“管理員調試模式”,Supabase在啟動時加了這個flag:

// 危險!生產環境絕對禁用
if os.Getenv("DEBUG_UNSAFE") == "true" {
    disableSandbox()
}

而某些部署文檔里寫著“設置DEBUG_UNSAFE=true啟用高級功能”——于是沙箱形同虛設。

安全加固:三步落地

別談理論,直接上能跑的代碼。

第一步:強制權限校驗中間件

在Server初始化時注入全局校驗:

server.Use(func(next mcp.Handler) mcp.Handler {
    return func(ctx mcp.Context, req mcp.Request) (mcp.Response, error) {
        // 從RPC注冊信息里讀取聲明的權限
        perms := server.GetRequiredPermissions(req.Method())
        for _, p := range perms {
            if !ctx.HasPermission(p) {
                return nil, mcp.ErrPermissionDenied
            }
        }
        return next(ctx, req)
    }
})

第二步:沙箱策略硬編碼

禁止運行時修改沙箱配置:

// 初始化時鎖定沙箱
sandbox := mcp.NewSandbox()
sandbox.AllowNetwork("supabase.com:5432")
sandbox.AllowFileRead("config/", "secrets/") // 僅限指定目錄
sandbox.Lock() // 后續調用disableSandbox()會panic

第三步:最小權限原則落地

給每個Agent分配獨立Token,權限精確到表:

{
  "permissions": ["read:rows"],
  "resources": ["users", "profiles"],
  "tenant_id": "prod_abc123"
}

而不是給前端Agent一個*:*通配符權限。

商業化前提:先守住底線

安全不是成本,是準入門檻。所有變現路徑都建立在“用戶信你不會丟數據”的基礎上。

可落地的合規路徑

  • 按查詢計費:Agent每次調用query方法,Server記錄tenant_id + table_name + row_count,生成賬單。權限校驗確保只計費被允許的查詢。
  • Agent市場審核:上架Agent必須通過沙箱掃描(檢測是否調用os/execnet.Dial等危險API),權限聲明必須匹配實際行為。
  • 數據代理服務:用戶授權后,Agent以read:anonymized_rows權限運行,在內存中脫敏(如email字段替換為hash),再返回結果——全程不落盤。

下一步:動手改一行代碼

現在打開你的MCP Server代碼,找到任意一個RPC handler。在第一行插入:

if !ctx.HasPermission("your_required_permission") {
    return nil, mcp.ErrPermissionDenied
}

然后刪掉所有DEBUG_UNSAFE環境變量相關邏輯。

做完這兩件事,你就比Supabase早半年避開這個漏洞。

返回首頁