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

?? MCP生態(tài)

Supabase MCP權(quán)限繞過漏洞分析與安全加固實(shí)踐

發(fā)布時(shí)間:2026-04-16 分類: MCP生態(tài)
摘要:Supabase MCP漏洞實(shí)錄:權(quán)限繞過與加固實(shí)踐漏洞現(xiàn)場:全庫SQL導(dǎo)出是怎么發(fā)生的Hacker News上那條“Supabase MCP Server裸奔導(dǎo)出全庫SQL”的帖子不是危言聳聽。真實(shí)情況是:攻擊者發(fā)一個(gè)特制的RPC請(qǐng)求,繞過所有權(quán)限檢查,直接拿到pg_catalog里所有表結(jié)構(gòu)、索引、視圖定義,再拼出SELECT * FROM ...語句批量執(zhí)行——整個(gè)數(shù)據(jù)庫的SQL sc...

封面

Supabase MCP漏洞實(shí)錄:權(quán)限繞過與加固實(shí)踐

漏洞現(xiàn)場:全庫SQL導(dǎo)出是怎么發(fā)生的

Hacker News上那條“Supabase MCP Server裸奔導(dǎo)出全庫SQL”的帖子不是危言聳聽。真實(shí)情況是:攻擊者發(fā)一個(gè)特制的RPC請(qǐng)求,繞過所有權(quán)限檢查,直接拿到pg_catalog里所有表結(jié)構(gòu)、索引、視圖定義,再拼出SELECT * FROM ...語句批量執(zhí)行——整個(gè)數(shù)據(jù)庫的SQL schema和數(shù)據(jù)就這么流出去了。

這不是協(xié)議缺陷,是Supabase的MCP Server實(shí)現(xiàn)漏掉了關(guān)鍵校驗(yàn)點(diǎn)。

權(quán)限校驗(yàn)在哪斷了鏈

問題出在元數(shù)據(jù)接口的處理邏輯里。MCP規(guī)范要求每個(gè)RPC調(diào)用必須經(jīng)過三道關(guān)卡:

  • 調(diào)用者身份可信(JWT簽名有效)
  • 請(qǐng)求操作在授權(quán)范圍內(nèi)(如read:tables
  • 目標(biāo)資源屬于該調(diào)用者可訪問的租戶/項(xiàng)目(租戶隔離)

但Supabase的list_tablesget_table_schema這兩個(gè)接口跳過了第二、第三步。只要能連上Server,任何未認(rèn)證或低權(quán)限用戶都能調(diào)用它們。

結(jié)果就是:一個(gè)本該只讀自己表的前端Agent,能查出整個(gè)PostgreSQL實(shí)例里所有數(shù)據(jù)庫的全部表結(jié)構(gòu)。

這不是MCP的鍋,是實(shí)現(xiàn)沒守規(guī)矩

MCP協(xié)議本身有明確的權(quán)限模型:每個(gè)RPC方法必須聲明所需權(quán)限(required_permissions: ["read:tables"]),Server必須在執(zhí)行前校驗(yàn)。沙箱機(jī)制也規(guī)定了Agent默認(rèn)無權(quán)訪問pg_catalog、無法跨數(shù)據(jù)庫查詢。

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

MCP安全機(jī)制:就兩件事,別搞復(fù)雜

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

權(quán)限控制:每個(gè)RPC入口必須校驗(yàn)

MCP的權(quán)限是動(dòng)詞+名詞組合:read:tableswrite:rows、exec:sql。不是角色RBAC,是操作級(jí)ABAC。

關(guān)鍵規(guī)則:

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

沙箱隔離:資源訪問必須顯式授權(quán)

MCP沙箱不是Docker容器,是運(yùn)行時(shí)約束:

  • Agent進(jìn)程默認(rèn)無文件系統(tǒng)訪問權(quán)限(os.Open直接panic)
  • 網(wǎng)絡(luò)只能連預(yù)注冊(cè)的endpoint(如supabase.com:5432
  • 數(shù)據(jù)庫連接自動(dòng)注入租戶schema前綴(tenant_123.users

違反規(guī)則的代碼會(huì)當(dāng)場失?。?/p>

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

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

Supabase漏洞復(fù)盤:兩個(gè)硬傷

Supabase的修復(fù)補(bǔ)?。╲1.23.1)暴露了最初的問題根源:

1. 元數(shù)據(jù)接口完全裸奔

list_schemas、get_column_info這些方法注冊(cè)時(shí)沒聲明任何權(quán)限要求:

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

導(dǎo)致MCP Server的全局權(quán)限中間件直接跳過校驗(yàn)。

2. 沙箱配置被手動(dòng)繞過

為支持“管理員調(diào)試模式”,Supabase在啟動(dòng)時(shí)加了這個(gè)flag:

// 危險(xiǎn)!生產(chǎn)環(huán)境絕對(duì)禁用
if os.Getenv("DEBUG_UNSAFE") == "true" {
    disableSandbox()
}

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

安全加固:三步落地

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

第一步:強(qiáng)制權(quán)限校驗(yàn)中間件

在Server初始化時(shí)注入全局校驗(yàn):

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

第二步:沙箱策略硬編碼

禁止運(yùn)行時(shí)修改沙箱配置:

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

第三步:最小權(quán)限原則落地

給每個(gè)Agent分配獨(dú)立Token,權(quán)限精確到表:

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

而不是給前端Agent一個(gè)*:*通配符權(quán)限。

商業(yè)化前提:先守住底線

安全不是成本,是準(zhǔn)入門檻。所有變現(xiàn)路徑都建立在“用戶信你不會(huì)丟數(shù)據(jù)”的基礎(chǔ)上。

可落地的合規(guī)路徑

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

下一步:動(dòng)手改一行代碼

現(xiàn)在打開你的MCP Server代碼,找到任意一個(gè)RPC handler。在第一行插入:

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

然后刪掉所有DEBUG_UNSAFE環(huán)境變量相關(guān)邏輯。

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

返回首頁
衡南县| 织金县| 阿巴嘎旗| 久治县| 宜丰县| 丁青县| 句容市| 沅江市| 桃园县| 达拉特旗| 许昌县| 密云县| 乾安县| 荣成市| 大方县| 张掖市| 普洱| 新绛县| 黑龙江省| 五华县| 龙陵县| 读书| 探索| 潞城市| 太仆寺旗| 昆山市| 彭泽县| 华安县| 上饶市| 滁州市| 台安县| 阜平县| 新竹市| 耿马| 贺兰县| 高陵县| 扶绥县| 保康县| 舞阳县| 旌德县| 乌拉特中旗|