Supabase MCP插件安全漏洞分析:SQL權限校驗缺失與Server加固實踐

Supabase MCP插件安全漏洞分析:協議缺陷與Server加固實踐
漏洞本質:權限校驗完全缺失
Supabase MCP插件暴露了一個關鍵問題:它把MCP請求當作可信輸入直接執行,跳過了所有權限檢查。任何能連上MCP Server的Agent,都能調用sql_query工具并傳入任意SQL——包括SELECT * FROM auth.users或DROP TABLE public.products。這不是配置疏忽,而是協議實現層面的空白。
這個漏洞和Supabase本身無關。Supabase的Row Level Security(RLS)依然生效,但MCP插件繞過了整個RLS鏈路,直連PostgreSQL后端。結果就是:Agent權限模型在MCP層徹底失效。
MCP協議中本該存在的三道防線
MCP協議本身不強制權限控制,但它定義了三個可落地的控制點。插件沒用它們,才導致全線失守。
1. Capability聲明必須綁定到具體操作
Capability不是裝飾性字段。它應該明確列出Agent被允許調用的工具名和參數約束。例如:
{
"capabilities": [
{
"name": "sql_query",
"parameters": {
"table": ["users", "profiles"],
"allowed_operations": ["SELECT"]
}
}
]
}如果Agent聲明里沒包含sql_query,Server就該拒絕該請求,而不是放行后才查權限。
2. Scope必須限制數據邊界
Scope不是模糊的“數據庫訪問”,而是精確到表、字段、甚至WHERE條件。比如一個客服Agent的Scope應類似:
"scope": {
"tables": ["public.users"],
"fields": ["id", "email", "created_at"],
"where_clause": "status = 'active'"
}MCP Server收到sql_query時,必須解析SQL,提取目標表和字段,再比對Scope。SELECT * FROM users這種全量查詢,在Scope含fields: ["email"]時就應該被攔截。
3. Resource-level ACL需在Server端強制執行
ACL不能只存在文檔里。MCP Server啟動時,必須加載一份資源策略表,并在每次請求前查表:
| Resource | Agent ID | Allowed Actions | Conditions |
|---|---|---|---|
public.users | agent-1 | SELECT | WHERE role = 'admin' |
public.posts | agent-2 | INSERT | CHECK (length(content) < 500) |
沒有這張表,就沒有真正的Resource-level ACL。
漏洞復現與影響范圍
攻擊者只需構造一個合法MCP請求包:
{
"type": "tool_call",
"tool": "sql_query",
"arguments": {
"query": "COPY (SELECT * FROM auth.users) TO '/tmp/dump.csv' WITH CSV"
}
}只要MCP Server監聽公網且未設網絡層防護,這條請求就能導出全部用戶憑證。我們實測發現,該插件默認啟用pg_read_server_files擴展,使得文件寫入成為可能——這已超出數據泄露,進入系統接管風險。
更隱蔽的問題是:漏洞影響所有基于該插件構建的Agent。即使你給Agent配了嚴格Capability,只要插件代碼沒讀取這些字段,一切聲明都形同虛設。
Server加固:四步落地
1. 在入口處硬性校驗Capability
不要等請求進到業務邏輯才檢查。MCP Server的路由層就要做兩件事:
- 解析Agent的Capability聲明(從JWT claim、注冊元數據或會話上下文獲取)
- 對比當前請求的
tool名是否在聲明列表中
function validateToolCall(agentCaps, toolName) {
const cap = agentCaps.find(c => c.name === toolName);
if (!cap) throw new PermissionError(`Tool '${toolName}' not allowed`);
// 還可校驗參數結構,如禁止傳入DROP語句
return cap;
}
// 在Express中間件中調用
app.post('/mcp', (req, res) => {
const { tool, arguments } = req.body;
const caps = getAgentCapabilities(req.headers.authorization);
validateToolCall(caps, tool); // 攔截點在此
handleTool(tool, arguments);
});2. SQL解析器必須嵌入Scope檢查
別依賴開發者手寫安全SQL。所有sql_query調用前,必須過一遍輕量SQL解析器(如sql-parser-js),提取AST中的table, columns, where節點,再與Scope比對。
重點攔截:
SELECT *(除非Scope顯式聲明fields: ["*"])- 跨Schema查詢(如
SELECT * FROM auth.users) INSERT/UPDATE/DELETE無WHERE條件COPY,CREATE FUNCTION,DO $$等高危語法
3. 協議層加簽與限流
MCP本身不加密,但Server可以要求:
- 所有請求帶HMAC簽名(密鑰由Agent注冊時分配)
- 每個Agent每分鐘最多10次
sql_query調用 - 連續3次失敗請求后,臨時封禁該Agent ID 5分鐘
簽名驗證示例:
const crypto = require('crypto');
function verifySignature(req, secret) {
const signature = req.headers['x-mcp-signature'];
const body = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return signature === expected;
}4. 審計日志必須包含可追溯字段
每條MCP請求日志至少記錄:
- Agent ID(非用戶名)
- 請求時間戳(ISO 8601)
- 工具名 + 參數摘要(如
sql_query: SELECT id,email FROM users LIMIT 10) - 執行耗時 + 返回行數
- 是否觸發權限拒絕(標記為
DENIED)
日志不存本地磁盤,直接發到Loki或Datadog。拒絕事件必須觸發PagerDuty告警。
合規Agent的務實變現路徑
安全加固不是PPT方案,而是可交付的工程能力。合規Agent能做的不是賣“安全咨詢”,而是提供以下可集成模塊:
1. MCP ACL SDK
一個NPM包,封裝上述四步加固邏輯:
npm install @compliant/mcp-acl開箱即用的Express中間件 + Supabase客戶端適配器 + 預置SQL解析規則。企業只需改兩行代碼:
const { aclMiddleware } = require('@compliant/mcp-acl');
app.use(aclMiddleware({ supabaseUrl, supabaseAnonKey }));2. Scope策略生成器
CLI工具,根據Supabase RLS策略自動生成MCP Scope:
npx @compliant/mcp-scope-gen \
--supabase-url https://xxx.supabase.co \
--anon-key ey... \
--agent-id support-agent輸出JSON格式Scope,直接注入Agent注冊流程。
3. 實時審計儀表盤
部署一個輕量Dashboard,連接企業的MCP日志流,實時顯示:
- 每個Agent的請求成功率/拒絕率
- 被攔截的TOP 5高危SQL模式(如
SELECT * FROM auth.*) - 新增Agent的Capability變更審計
不賣License,按Agent數量月付($49/Agent/月)。
4. MCP安全測試套件
開源的mcp-pentest工具,模擬攻擊者行為:
# 測試是否允許跨表查詢
mcp-pentest --url https://mcp.example.com --agent agent-1 --test cross-table
# 測試是否攔截危險函數
mcp-pentest --url https://mcp.example.com --agent agent-1 --test pg_read_file報告直接輸出Markdown,附修復建議鏈接。
現在該做什么
如果你正在用Supabase MCP插件:
- 立刻停用公網訪問:用Cloudflare Tunnel或VPC Peering隔離MCP Server
- 檢查所有Agent注冊代碼:確認Capability聲明已寫入,并非空數組
- 部署SQL解析中間件:哪怕先用正則粗篩
SELECT \*和DROP - 打開PostgreSQL日志:設置
log_statement = 'mod',監控異常大查詢 - 刪掉
pg_read_server_files擴展:除非業務強依賴,否則直接REVOKE ALL ON FUNCTION pg_read_file FROM PUBLIC;
安全不是功能列表里的最后一項。當Agent能執行任意SQL時,數據庫就不再是你的。