MCP Server插件權限漏洞分析:修復未認證訪問導致的數據庫泄露風險

MCP Server插件權限漏洞剖析:MCP協議安全邊界實戰筆記
一、真實問題現場
某MCP Server插件上線后不久,客戶反饋數據庫被全量導出。日志顯示,一個未認證的HTTP請求調用了/tools/list_tools端點,返回結果里赫然包含users、payments、auth_sessions等表名,以及字段定義和索引信息。攻擊者據此構造SQL注入載荷,繞過應用層直接讀取敏感數據。
這不是理論風險——是已發生的生產事故。
二、漏洞根因拆解
權限校驗完全缺失
插件收到MCP請求時,直接執行工具邏輯,未檢查request.context.permissions字段。MCP協議要求Server在調用任何工具前驗證權限上下文,但該插件把permissions當成了可選字段處理。
后果很直接:任意客戶端(包括curl、Postman)都能觸發list_tools,而這個工具又沒做輸入過濾或輸出脫敏。
mcp.tools.list_tools暴露結構信息
該工具本意是供Agent運行時動態發現可用能力,但插件實現中:
- 直接返回了數據庫連接池的元數據(
pg_catalog查詢結果) - 未剝離
information_schema中的敏感字段(如column_default含密碼哈希邏輯) - 返回體未做角色過濾——管理員和訪客看到的工具列表完全一致
元數據不是“輔助信息”,它是攻擊鏈的第一塊墊腳石。
RBAC形同虛設
插件聲明支持RBAC,但實際只做了兩件事:
- 在配置文件里寫了
"role": "admin"硬編碼 - 所有工具函數都忽略
context.role參數
結果:普通用戶調用delete_user時,代碼路徑和管理員完全相同。
三、Supabase場景下的放大效應
當MCP Server對接Supabase時,問題更致命。Supabase默認開啟Row Level Security(RLS),但前提是客戶端必須提供有效JWT。而該插件:
- 用服務端私鑰直連Supabase,繞過RLS
list_tools返回的表名直接映射到Supabase的公開視圖名- 攻擊者拿到
auth.users表結構后,立刻用https://your-project.supabase.co/rest/v1/auth.users?select=*發起跨域請求
Supabase沒破防,是MCP Server把門鑰匙交給了路人。
四、守住MCP安全邊界的實操要點
協議規范的關鍵約束
MCP協議對權限的強制要求就三條,必須落地:
- 所有工具調用前,必須校驗
context.permissions是否包含當前操作所需scope list_tools返回的工具列表,必須按context.role動態過濾(例如user角色看不到db.dump)context對象不可被客戶端篡改——Server需用簽名驗證其完整性
Server開發必須做的三件事
權限校驗前置
在路由層統一攔截,拒絕permissions為空或缺失必要scope的請求:def require_permission(scope: str): if not request.context.permissions or scope not in request.context.permissions: raise PermissionError(f"Missing permission: {scope}")工具元數據嚴格分級
list_tools返回值按角色隔離:guest: 僅返回weather.get、calculator.adduser: 增加db.query(但隱藏table參數枚舉)admin: 才返回db.dump、system.exec
禁用危險反射
禁止工具函數通過getattr()動態調用數據庫方法。所有DB操作必須顯式聲明依賴的表和字段,并在啟動時注冊白名單:# 正確:白名單驅動 DB_OPERATIONS = { "users.read": {"tables": ["users"], "fields": ["id", "email"]}, "payments.write": {"tables": ["payments"], "fields": ["amount", "status"]} }
商業化案例中的硬性紅線
醫療AI Agent的MCP Server部署時,我們強制執行:
- 所有數據庫操作必須走預編譯語句(
PreparedStatement),禁止拼接SQL context.permissions由OIDC ID Token解碼生成,不接受客戶端傳入的任何權限字段- 每次
list_tools調用觸發審計日志,記錄client_ip、user_role、timestamp - 敏感工具(如
db.export)需二次確認,且導出文件自動加密+72小時過期
這些不是“最佳實踐”,是HIPAA合規的底線。
五、m.nhjb.com.cn的定位
m.nhjb.com.cn不做MCP協議翻譯器,只做三件事:
- 把協議規范里的安全條款,轉換成可測試的代碼檢查清單(比如“
list_tools響應體必須包含role字段”) - 公開真實漏洞的復現環境和修復diff(含Supabase、Postgres、MongoDB三套方案)
- 拆解商業化Agent的權限模型設計——從醫療到金融,每份架構圖都標注了MCP協議如何嵌入現有IAM體系
六、立刻能做的四件事
- 檢查你的
list_tools實現
用curl發個無權限請求:curl -X POST http://localhost:3000/tools/list_tools,看返回里有沒有數據庫表名或系統路徑。 給所有工具加權限守衛
在每個工具函數開頭插入:assert "db.read" in context.permissions, "Permission denied"- 刪掉所有
eval()、exec()、getattr(..., user_input)
MCP工具必須是純函數,輸入輸出完全可預測。 用Supabase RLS做最后一道閘
即使MCP Server出問題,也讓數據庫自己攔住非法查詢:ALTER TABLE users ENABLE ROW LEVEL SECURITY; CREATE POLICY select_own ON users FOR SELECT USING (auth.uid() = id);