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

?? MCP生態(tài)

Supabase MCP Server鑒權(quán)加固指南:解決租戶隔離與權(quán)限校驗(yàn)漏洞

發(fā)布時(shí)間:2026-04-15 分類: MCP生態(tài)
摘要:MCP生態(tài)實(shí)戰(zhàn)價(jià)值:Supabase漏洞反思與MCP Server鑒權(quán)加固Supabase漏洞事件復(fù)盤Hacker News上一篇關(guān)于“Supabase MCP漏洞可導(dǎo)出全庫(kù)SQL”的討論,實(shí)際指向一個(gè)更具體的問(wèn)題:Supabase的MCP服務(wù)端未對(duì)/mcp/export端點(diǎn)做租戶隔離和操作權(quán)限校驗(yàn)。攻擊者只需構(gòu)造一個(gè)合法認(rèn)證頭,就能觸發(fā)全庫(kù)導(dǎo)出,拿到所有表結(jié)構(gòu)和數(shù)據(jù)。這不是MCP協(xié)議本身的...

封面

MCP生態(tài)實(shí)戰(zhàn)價(jià)值:Supabase漏洞反思與MCP Server鑒權(quán)加固

Supabase漏洞事件復(fù)盤

Hacker News上一篇關(guān)于“Supabase MCP漏洞可導(dǎo)出全庫(kù)SQL”的討論,實(shí)際指向一個(gè)更具體的問(wèn)題:Supabase的MCP服務(wù)端未對(duì)/mcp/export端點(diǎn)做租戶隔離和操作權(quán)限校驗(yàn)。攻擊者只需構(gòu)造一個(gè)合法認(rèn)證頭,就能觸發(fā)全庫(kù)導(dǎo)出,拿到所有表結(jié)構(gòu)和數(shù)據(jù)。

這不是MCP協(xié)議本身的漏洞,而是Supabase在實(shí)現(xiàn)MCP Server時(shí)跳過(guò)了三個(gè)關(guān)鍵環(huán)節(jié):

  • 沒(méi)綁定請(qǐng)求上下文到用戶身份(例如沒(méi)提取JWT中的tenant_idrole字段)
  • 沒(méi)校驗(yàn)操作語(yǔ)義(export屬于高危動(dòng)作,不應(yīng)開放給普通用戶)
  • 沒(méi)限制導(dǎo)出范圍(默認(rèn)導(dǎo)出全部schema,未強(qiáng)制指定--schema=app_public之類約束)

這個(gè)案例暴露的不是協(xié)議缺陷,而是MCP Server開發(fā)中常見的“協(xié)議搬運(yùn)工”陷阱:照搬協(xié)議定義,卻忽略業(yè)務(wù)語(yǔ)義層的訪問(wèn)控制。

MCP Server必須守住的三道防線

MCP協(xié)議本身不規(guī)定鑒權(quán)模型,它只定義消息格式和路由規(guī)則。Server實(shí)現(xiàn)者必須自己補(bǔ)上這三層防護(hù):

1. 上下文綁定:把請(qǐng)求錨定到真實(shí)身份

MCP請(qǐng)求里帶Authorization頭,但不能只驗(yàn)證token是否有效。要解析出subtenant_idscope等聲明,并在后續(xù)所有處理中顯式傳遞。

# 正確做法:解析并注入上下文
from flask import g, request
import jwt

def auth_middleware():
    token = request.headers.get('Authorization', '').replace('Bearer ', '')
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        g.user_id = payload['sub']
        g.tenant_id = payload['tenant_id']
        g.scopes = set(payload.get('scope', '').split())
    except Exception:
        return {'error': 'Invalid token'}, 401

@app.before_request
def before_request():
    return auth_middleware()

2. 動(dòng)作分級(jí):按操作敏感度動(dòng)態(tài)授權(quán)

MCP操作不能一刀切。list_tools可以公開,export_db必須要求admin:tenant scope,delete_tool則需額外校驗(yàn)工具歸屬。

def require_scope(*required_scopes):
    def decorator(f):
        def wrapped(*args, **kwargs):
            missing = set(required_scopes) - g.scopes
            if missing:
                return {'error': f'Missing scopes: {missing}'}, 403
            # 額外檢查:export_db必須限定schema
            if 'export_db' in required_scopes and request.args.get('schema') != g.tenant_id:
                return {'error': 'Export schema must match tenant'}, 403
            return f(*args, **kwargs)
        return wrapped
    return decorator

@app.route('/mcp/export', methods=['POST'])
@require_scope('export_db')
def export_db():
    # 此時(shí)g.tenant_id和scopes均已驗(yàn)證
    return run_export(g.tenant_id)

3. 數(shù)據(jù)沙箱:用數(shù)據(jù)庫(kù)能力做物理隔離

別靠應(yīng)用層if-else過(guò)濾數(shù)據(jù)。用PostgreSQL的Row Level Security(RLS)或MySQL的Schema級(jí)權(quán)限,讓數(shù)據(jù)庫(kù)自己攔住越權(quán)查詢。

-- PostgreSQL RLS策略示例
ALTER TABLE public.tools ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON public.tools
  USING (tenant_id = current_setting('app.current_tenant', true)::uuid);

然后在應(yīng)用層設(shè)置會(huì)話變量:

@app.before_request
def set_tenant_context():
    db.execute("SET app.current_tenant = %s", (g.tenant_id,))

這樣即使代碼漏掉某處校驗(yàn),數(shù)據(jù)庫(kù)也會(huì)拒絕返回其他租戶的數(shù)據(jù)。

鑒權(quán)加固不是加功能,是改流程

很多團(tuán)隊(duì)把鑒權(quán)當(dāng)成“加個(gè)中間件”,結(jié)果變成層層嵌套的裝飾器。真正有效的加固,是把權(quán)限判斷嵌入到核心路徑里:

  • 工具注冊(cè)時(shí),記錄owner_tenant_id
  • 請(qǐng)求解析后,立即查tools表確認(rèn)該工具屬于當(dāng)前租戶
  • 執(zhí)行前,用pg_advisory_xact_lock()對(duì)租戶ID加事務(wù)鎖,防并發(fā)沖突
  • 日志里強(qiáng)制記錄tenant_iduser_idactionduration_ms
@app.route('/mcp/execute', methods=['POST'])
def execute_tool():
    tool_name = request.json['tool']
    # 1. 查工具歸屬
    tool = db.fetch_one("SELECT * FROM tools WHERE name = %s AND tenant_id = %s", 
                        (tool_name, g.tenant_id))
    if not tool:
        return {'error': 'Tool not found or access denied'}, 404
    
    # 2. 加租戶鎖(防并發(fā)修改配置)
    db.execute("SELECT pg_advisory_xact_lock(hashtext(%s))", (g.tenant_id,))
    
    # 3. 執(zhí)行并計(jì)時(shí)
    start = time.time()
    result = run_tool(tool, request.json['args'])
    duration = int((time.time() - start) * 1000)
    
    # 4. 記錄審計(jì)日志(含租戶上下文)
    audit_log.insert({
        'tenant_id': g.tenant_id,
        'user_id': g.user_id,
        'action': 'execute_tool',
        'tool': tool_name,
        'duration_ms': duration,
        'status': 'success' if result else 'failed'
    })
    
    return result

商業(yè)化落地的關(guān)鍵:把安全設(shè)計(jì)變成客戶能感知的價(jià)值

金融客戶不關(guān)心你用了RBAC還是ABAC,但他們清楚知道:“如果你們的MCP Server被攻破,我的交易數(shù)據(jù)會(huì)不會(huì)流到競(jìng)爭(zhēng)對(duì)手那里?”

所以商業(yè)化路徑要倒過(guò)來(lái)推:

1. 從合規(guī)需求反推技術(shù)方案

  • GDPR → 要求數(shù)據(jù)不出境 → 在MCP Server里加region字段,路由時(shí)強(qiáng)制匹配
  • HIPAA → 要求審計(jì)日志留存6年 → 把audit_log表設(shè)為分區(qū)表,按月自動(dòng)歸檔
  • 等保三級(jí) → 要求雙因素登錄 → 在token簽發(fā)前,校驗(yàn)TOTP code

2. 把防護(hù)能力包裝成可售特性

客戶痛點(diǎn)技術(shù)實(shí)現(xiàn)產(chǎn)品話術(shù)
怕多租戶數(shù)據(jù)混雜RLS + tenant_id強(qiáng)綁定“物理級(jí)租戶隔離,通過(guò)PG官方RLS策略保障”
怕誤刪生產(chǎn)數(shù)據(jù)DELETE操作需二次確認(rèn)+72小時(shí)回收站“企業(yè)級(jí)操作保險(xiǎn)箱,刪除自動(dòng)進(jìn)回收站”
怕API密鑰泄露token支持細(xì)粒度scope + 1小時(shí)過(guò)期“最小權(quán)限令牌,支持按工具、按環(huán)境分發(fā)”

3. 用客戶自己的環(huán)境驗(yàn)證效果

別只講PPT。給POC客戶部署一個(gè)帶審計(jì)看板的實(shí)例:

  • 實(shí)時(shí)顯示“今日攔截越權(quán)請(qǐng)求:17次”
  • 展示一條被拒請(qǐng)求的完整鏈路:JWT解析→scope校驗(yàn)失敗→拒絕→寫入審計(jì)日志
  • 提供一鍵生成合規(guī)報(bào)告的按鈕(含GDPR/HIPAA條款映射)

真實(shí)項(xiàng)目踩坑記錄

我們給一家跨境支付公司上線MCP Server時(shí),在/mcp/transfer接口栽過(guò)跟頭:

  • 初始版本只校驗(yàn)了transfer_funds scope,沒(méi)校驗(yàn)from_account是否屬于當(dāng)前租戶
  • 攻擊者用自己租戶的token,把from_account改成另一家客戶的賬戶ID,成功轉(zhuǎn)出資金
  • 修復(fù)方案不是加if判斷,而是:

    1. 在數(shù)據(jù)庫(kù)加外鍵約束:transfers.from_account_id → accounts.id + accounts.tenant_id = transfers.tenant_id
    2. 查詢時(shí)強(qiáng)制JOIN:SELECT * FROM transfers t JOIN accounts a ON t.from_account_id = a.id AND a.tenant_id = %s
    3. 所有account ID參數(shù),統(tǒng)一走uuid類型校驗(yàn),防SQL注入

這次事故讓我們確認(rèn)一條原則:鑒權(quán)邏輯必須下沉到數(shù)據(jù)訪問(wèn)層,應(yīng)用層只做快速失敗(fast fail),不承擔(dān)最終裁決責(zé)任。

下一步行動(dòng)清單

  • [ ] 檢查現(xiàn)有MCP Server所有端點(diǎn),標(biāo)記出exportdeleteexec類高危動(dòng)作
  • [ ] 給每個(gè)高危端點(diǎn)補(bǔ)上tenant_id顯式校驗(yàn),刪掉所有“全局查詢”SQL
  • [ ] 在數(shù)據(jù)庫(kù)啟用RLS或?qū)?yīng)隔離機(jī)制,用EXPLAIN ANALYZE驗(yàn)證策略生效
  • [ ] 把審計(jì)日志字段從user_id擴(kuò)展為{tenant_id,user_id,ip,ua},接入SIEM系統(tǒng)
  • [ ] 更新客戶文檔,在“安全特性”章節(jié)直接寫明:“所有導(dǎo)出操作強(qiáng)制限定schema,無(wú)法跨租戶”
返回首頁(yè)