MCP協(xié)議Server鑒權(quán)加固實(shí)戰(zhàn):租戶隔離與SQL執(zhí)行安全合規(guī)方案
MCP協(xié)議實(shí)戰(zhàn)解析:Server鑒權(quán)加固與合規(guī)商業(yè)化路徑
Supabase漏洞事件:一個(gè)真實(shí)的權(quán)限失控現(xiàn)場
Hacker News上那篇題為“Supabase MCP漏洞可導(dǎo)出全庫SQL”的帖子不是假設(shè),是真實(shí)發(fā)生的越權(quán)讀取。攻擊者沒用0day,只靠一個(gè)未校驗(yàn)租戶上下文的/v1/sql端點(diǎn),加上默認(rèn)開啟的pg_dump權(quán)限,就拿到了整個(gè)PostgreSQL實(shí)例的結(jié)構(gòu)和數(shù)據(jù)。
問題不在Supabase本身,而在MCP Server實(shí)現(xiàn)層:它把“支持MCP協(xié)議”等同于“實(shí)現(xiàn)了MCP傳輸層”,卻漏掉了最關(guān)鍵的租戶隔離邏輯——沒有在SQL執(zhí)行前綁定current_user、沒做schema級(jí)訪問控制、也沒校驗(yàn)請(qǐng)求頭里的X-MCP-Tenant-ID是否匹配連接池中的實(shí)際租戶。
這個(gè)漏洞暴露的不是MCP協(xié)議設(shè)計(jì)缺陷,而是Server開發(fā)者對(duì)協(xié)議語義的誤讀:MCP不定義權(quán)限模型,它只約定數(shù)據(jù)如何流動(dòng);權(quán)限必須由Server自己落地,且必須貫穿到每一行SQL、每一個(gè)HTTP響應(yīng)頭、每一次文件寫入。
MCP Server權(quán)限控制的三個(gè)落地層
MCP協(xié)議文檔里寫的是“Server應(yīng)確保多租戶數(shù)據(jù)隔離”,但沒說怎么確保。真正起作用的只有三層:
1. 連接層隔離(最基礎(chǔ)也最容易被繞過)
- 每個(gè)租戶必須使用獨(dú)立數(shù)據(jù)庫連接池,不能復(fù)用同一連接處理多個(gè)租戶請(qǐng)求
- 連接建立時(shí)強(qiáng)制執(zhí)行
SET search_path TO tenant_123, public,而非依賴應(yīng)用層拼接schema前綴 - 使用
pgbouncer時(shí)禁用pool_mode = transaction,改用pool_mode = session
2. 查詢層攔截(核心防線)
# 正確做法:在SQL解析階段注入租戶約束
def execute_sql(tenant_id: str, raw_sql: str) -> List[dict]:
# 1. 攔截DDL(禁止租戶創(chuàng)建新schema)
if re.search(r'\b(CREATE|ALTER|DROP)\s+(SCHEMA|DATABASE)\b', raw_sql, re.I):
raise PermissionError("Tenant not allowed to manage schemas")
# 2. 自動(dòng)重寫SELECT語句,添加租戶過濾
if raw_sql.strip().upper().startswith('SELECT'):
# 解析AST,找到FROM子句,對(duì)每個(gè)表注入WHERE tenant_id = ?
rewritten = inject_tenant_filter(raw_sql, tenant_id)
return run_query(rewritten, tenant_id)
# 3. 其他語句直接校驗(yàn)權(quán)限位
if not has_permission(tenant_id, 'sql_exec'):
raise PermissionError("SQL execution denied for tenant")3. 響應(yīng)層凈化(最后一道閘)
- 所有返回的JSON響應(yīng)必須經(jīng)過
sanitize_response()過濾,移除pg_stat_activity等系統(tǒng)視圖中暴露的進(jìn)程信息 - 文件導(dǎo)出(如CSV/SQL dump)必須用臨時(shí)租戶專用目錄,路徑格式為
/tmp/tenant_{id}_{uuid}/ - 錯(cuò)誤消息禁用
debug=True,避免泄露表名、字段名、索引名
鑒權(quán)加固:從補(bǔ)丁到架構(gòu)
Supabase事件后,我們重構(gòu)了MCP Server的鑒權(quán)鏈,不再依賴單一Token校驗(yàn),而是構(gòu)建三級(jí)校驗(yàn):
- 傳輸層校驗(yàn):驗(yàn)證
Authorization: Bearer <JWT>簽名與有效期 - 協(xié)議層校驗(yàn):檢查
X-MCP-Request-ID是否在白名單內(nèi)(防重放),X-MCP-Client-Version是否兼容 - 業(yè)務(wù)層校驗(yàn):根據(jù)
X-MCP-Tenant-ID查租戶策略表,確認(rèn)本次請(qǐng)求的操作類型(sql_exec,file_read,config_update)是否被授權(quán)
關(guān)鍵改動(dòng)在tenant_policy表結(jié)構(gòu):
CREATE TABLE tenant_policy (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
operation TEXT NOT NULL CHECK (operation IN ('sql_exec', 'file_read', 'file_write', 'config_update')),
allowed BOOLEAN DEFAULT true,
max_rows INTEGER DEFAULT 10000,
timeout_ms INTEGER DEFAULT 5000,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 策略生效示例
INSERT INTO tenant_policy (tenant_id, operation, allowed, max_rows)
VALUES ('acme-corp', 'sql_exec', true, 50000);每次SQL執(zhí)行前,查詢該表并動(dòng)態(tài)設(shè)置statement_timeout和LIMIT:
-- 在連接中執(zhí)行
SET statement_timeout = 5000;
-- 在SQL末尾自動(dòng)追加
-- LIMIT 50000商業(yè)化落地:一個(gè)Agent項(xiàng)目的硬核變現(xiàn)路徑
我們做的跨云數(shù)據(jù)同步Agent,上線6個(gè)月后開始收費(fèi)。沒走“免費(fèi)版限功能”路線,而是用安全能力倒逼付費(fèi):
收費(fèi)錨點(diǎn)直指合規(guī)痛點(diǎn)
| 功能 | 免費(fèi)版 | 付費(fèi)版($299/月) |
|---|---|---|
| 租戶數(shù)據(jù)隔離 | 進(jìn)程級(jí)隔離 | 數(shù)據(jù)庫實(shí)例級(jí)隔離 |
| SQL審計(jì)日志 | 僅記錄成功操作 | 記錄完整SQL+參數(shù)+執(zhí)行計(jì)劃 |
| 敏感字段脫敏 | 不支持 | 自動(dòng)識(shí)別PII字段并AES加密 |
| 合規(guī)報(bào)告 | 無 | 自動(dòng)生成SOC2/ISO27001模板 |
客戶采購決策不是因?yàn)椤肮δ芏唷?,而是因?yàn)榉▌?wù)部明確要求:“生產(chǎn)環(huán)境必須滿足租戶間數(shù)據(jù)庫實(shí)例隔離”。
關(guān)鍵轉(zhuǎn)化動(dòng)作
定價(jià)頁不寫功能列表,寫合規(guī)聲明:
“企業(yè)版部署即滿足GDPR第32條‘適當(dāng)技術(shù)措施’要求,所有租戶數(shù)據(jù)存儲(chǔ)于物理隔離的AWS RDS實(shí)例,VPC間無網(wǎng)絡(luò)互通。”
- 免費(fèi)試用限制真實(shí)場景:
免費(fèi)用戶只能連接本地PostgreSQL,無法添加AWS RDS或Cloud SQL連接——讓客戶在第一天就意識(shí)到“云環(huán)境需要企業(yè)版”。 - 銷售話術(shù)聚焦故障成本:
“一次租戶數(shù)據(jù)泄露的平均修復(fù)成本是$380萬(IBM《2023數(shù)據(jù)泄露成本報(bào)告》)。企業(yè)版隔離方案的成本,不到一次事故的0.1%?!?/li>
下一步:把鑒權(quán)變成產(chǎn)品能力
別再把權(quán)限控制當(dāng)成安全團(tuán)隊(duì)的補(bǔ)丁任務(wù)。把它做成可配置、可審計(jì)、可計(jì)費(fèi)的產(chǎn)品模塊:
- 在管理后臺(tái)開放
tenant_policy編輯界面,讓客戶自行開關(guān)file_read權(quán)限 - 將SQL審計(jì)日志接入客戶現(xiàn)有SIEM系統(tǒng)(Splunk/Sentinel),作為增值集成項(xiàng)收費(fèi)
- 對(duì)高頻查詢自動(dòng)觸發(fā)
EXPLAIN ANALYZE,生成性能報(bào)告——按報(bào)告份數(shù)收取分析費(fèi)
真正的商業(yè)化,始于把安全約束翻譯成客戶愿意付費(fèi)的確定性。