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

?? MCP生態(tài)

Supabase MCP插件安全漏洞解析:協(xié)議層鑒權(quán)缺失導(dǎo)致SQL直連風(fēng)險

發(fā)布時間:2026-04-12 分類: MCP生態(tài)
摘要:Supabase MCP插件安全隱患:開源不等于安全,協(xié)議層鑒權(quán)缺失才是關(guān)鍵問題本質(zhì):MCP endpoint 沒有協(xié)議級防護Supabase 的 MCP 插件暴露了一個 /mcp endpoint,它直接將客戶端傳入的 SQL 查詢轉(zhuǎn)發(fā)給數(shù)據(jù)庫執(zhí)行。這個設(shè)計跳過了所有應(yīng)用層訪問控制——沒有用戶身份校驗、沒有權(quán)限分級、沒有操作白名單。只要能發(fā) HTTP 請求到這個地址,就能讀取任意表、導(dǎo)出全...

Supabase MCP插件安全隱患:開源不等于安全,協(xié)議層鑒權(quán)缺失才是關(guān)鍵

問題本質(zhì):MCP endpoint 沒有協(xié)議級防護

Supabase 的 MCP 插件暴露了一個 /mcp endpoint,它直接將客戶端傳入的 SQL 查詢轉(zhuǎn)發(fā)給數(shù)據(jù)庫執(zhí)行。這個設(shè)計跳過了所有應(yīng)用層訪問控制——沒有用戶身份校驗、沒有權(quán)限分級、沒有操作白名單。只要能發(fā) HTTP 請求到這個地址,就能讀取任意表、導(dǎo)出全庫、甚至刪庫。

這不是配置疏忽,是協(xié)議實現(xiàn)層面的缺失:MCP 規(guī)范本身要求服務(wù)端對每個操作做鑒權(quán)和沙箱約束,但當前插件把這部分完全交給了上層應(yīng)用,而多數(shù)開發(fā)者根本沒意識到這里需要補漏。

協(xié)議層該有的兩道防線

鑒權(quán)不是可選項

MCP 協(xié)議明確要求服務(wù)端驗證調(diào)用方身份,并基于角色或策略限制其可執(zhí)行的操作類型(如只讀、只查特定表)。Supabase 插件目前把 Authorization 頭直接忽略,所有請求都以數(shù)據(jù)庫超級用戶身份執(zhí)行。

后果很直接:

  • 攻擊者用 curl -X POST https://your-project.supabase.co/mcp -d '{"query":"SELECT * FROM users"}' 就能拿到全部用戶數(shù)據(jù)
  • 如果數(shù)據(jù)庫連接配置了高權(quán)限賬號,DROP TABLE、COPY TO PROGRAM 等危險操作也能成功

沙箱不是性能負擔,是必要隔離

沙箱機制要解決兩個問題:

  • 語法隔離:禁止 DELETE/UPDATE/INSERT/TRUNCATE 等寫操作,只允許 SELECT
  • 語義隔離:限制 SELECT 范圍,比如禁止跨 schema 查詢、禁止 information_schema 探針、限制返回行數(shù)

當前插件不做任何解析,原樣執(zhí)行傳入的 SQL 字符串。一個 UNION SELECT pg_read_file('/etc/passwd') 就可能觸發(fā)數(shù)據(jù)庫側(cè)信道泄露。

實際風(fēng)險場景

全庫導(dǎo)出無需提權(quán)

攻擊者構(gòu)造如下請求即可導(dǎo)出整個數(shù)據(jù)庫結(jié)構(gòu)和內(nèi)容:

curl -X POST https://your-project.supabase.co/mcp \
  -H "Content-Type: application/json" \
  -d '{
        "query": "SELECT table_name FROM information_schema.tables WHERE table_schema = \'public\'"
      }'

拿到表名后,循環(huán)執(zhí)行 SELECT * FROM <table>,幾條 shell 腳本就能完成全量 dump。Supabase 默認開啟 Row Level Security(RLS),但 MCP 插件繞過了 RLS——它直連數(shù)據(jù)庫,不走 PostgREST 層。

敏感數(shù)據(jù)在 AI 流水線中裸奔

很多 AI Agent 項目用 MCP 插件做“數(shù)據(jù)庫工具調(diào)用”,把用戶會話 ID、支付記錄、原始日志等直接喂給 LLM。一旦 MCP endpoint 泄露,這些數(shù)據(jù)就變成明文 CSV 流向外部。

更危險的是:LLM 可能被誘導(dǎo)生成惡意查詢。比如用戶輸入“幫我刪掉測試數(shù)據(jù)”,Agent 解析成 DELETE FROM logs WHERE is_test = true 并提交——插件照單執(zhí)行,且無審計日志。

寫操作導(dǎo)致服務(wù)雪崩

UPDATE accounts SET balance = balance - 100 WHERE user_id = 'attacker' 這類語句不會報錯,但會污染業(yè)務(wù)數(shù)據(jù)。更糟的是 VACUUM FULLCREATE INDEX CONCURRENTLY 等維護命令可能鎖表,讓整個應(yīng)用不可用。

怎么修:在 endpoint 層加兩道硬閘

必須加鑒權(quán):JWT 校驗 + 權(quán)限映射

不要依賴網(wǎng)絡(luò)層防火墻或 IP 白名單。每個請求必須攜帶有效 JWT,且 token payload 中需聲明 allowed_tablesallowed_operations。

from flask import Flask, request, jsonify
import jwt
from datetime import datetime

app = Flask(__name__)

def require_mcp_auth(f):
    def decorated(*args, **kwargs):
        auth = request.headers.get('Authorization')
        if not auth or not auth.startswith('Bearer '):
            return jsonify({'error': 'Missing or invalid Authorization header'}), 401
        
        token = auth[7:]
        try:
            payload = jwt.decode(token, 'your-supabase-jwt-secret', algorithms=['HS256'])
            # 強制檢查權(quán)限字段
            if 'allowed_tables' not in payload or 'allowed_operations' not in payload:
                return jsonify({'error': 'Invalid token: missing permissions'}), 403
            request.mcp_permissions = payload
        except jwt.ExpiredSignatureError:
            return jsonify({'error': 'Token expired'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'error': 'Invalid token'}), 401
        return f(*args, **kwargs)
    return decorated

@app.route('/mcp', methods=['POST'])
@require_mcp_auth
def mcp_handler():
    data = request.get_json()
    query = data.get('query', '').strip()
    # 后續(xù)校驗 query 是否符合 permissions...

必須加沙箱:SQL 解析 + 白名單執(zhí)行

別用字符串拼接或正則匹配禁用關(guān)鍵詞——%00DELETE、注釋繞過、Unicode 變體都能繞過。用真正的 SQL 解析器(如 sqlparse)提取 AST,只允許 SELECT 類型節(jié)點,且 FROM 子句中的表名必須在 allowed_tables 列表中。

import sqlparse
from sqlparse.sql import IdentifierList, Identifier, Where, Comparison
from sqlparse.tokens import Keyword, DML

def validate_query(query: str, allowed_tables: list) -> bool:
    parsed = sqlparse.parse(query)[0]
    
    # 檢查是否為 SELECT
    if not parsed.token_first().ttype is DML and parsed.token_first().value.upper() != 'SELECT':
        return False
    
    # 提取所有表名
    tables = set()
    for token in parsed.flatten():
        if isinstance(token, Identifier) and token.has_alias():
            tables.add(token.get_real_name())
        elif isinstance(token, IdentifierList):
            for identifier in token.get_identifiers():
                if hasattr(identifier, 'get_real_name'):
                    tables.add(identifier.get_real_name())
    
    # 檢查表名是否都在白名單中
    return all(table in allowed_tables for table in tables)

@app.route('/mcp', methods=['POST'])
@require_mcp_auth
def mcp_handler():
    data = request.get_json()
    query = data.get('query', '').strip()
    
    if not validate_query(query, request.mcp_permissions['allowed_tables']):
        return jsonify({'error': 'Query violates table access policy'}), 403
    
    # 執(zhí)行查詢(使用參數(shù)化,避免二次注入)
    with db_engine.connect() as conn:
        result = conn.execute(text(query))
        return jsonify([dict(row) for row in result]), 200

真實項目怎么落地

不要自己重寫 MCP Server

Supabase 官方插件的問題在于它把協(xié)議實現(xiàn)簡化成了“HTTP → SQL”管道。更穩(wěn)妥的做法是:

  • MCP SDK 啟動標準 server
  • tool_call handler 中注入鑒權(quán)邏輯
  • 所有數(shù)據(jù)庫操作走 Supabase Client(自動帶 RLS)而非直連

這樣既能復(fù)用社區(qū)規(guī)范,又把權(quán)限控制收回到應(yīng)用層。

關(guān)鍵檢查清單

部署前確認以下五點:

  • ? MCP endpoint 的數(shù)據(jù)庫連接賬號權(quán)限最小化(只讀 + 僅限必要 schema)
  • ? JWT secret 與 Supabase 項目密鑰分離,不硬編碼在代碼里
  • ? allowed_tables 按業(yè)務(wù)場景動態(tài)生成(如客服 Agent 只能查 ticketsusers
  • ? 所有 SELECT 查詢自動加上 LIMIT 1000,防止大結(jié)果集拖垮內(nèi)存
  • ? 日志記錄每次 MCP 調(diào)用的 token subject、表名、查詢哈希(不記原始 SQL)

商業(yè)項目必須簽 DPA

如果你的 Agent 服務(wù)把客戶數(shù)據(jù)傳給第三方 MCP provider,必須簽數(shù)據(jù)處理協(xié)議(DPA),明確:

  • provider 不得存儲原始數(shù)據(jù)
  • 查詢?nèi)罩颈A舨怀^ 7 天
  • 審計權(quán)開放給客戶(提供 API 查看調(diào)用記錄)
  • 違約賠償條款(例如每條泄露記錄罰 $500)

GDPR 和國內(nèi)《個人信息保護法》都把這種“通過協(xié)議接口傳輸數(shù)據(jù)”的行為認定為委托處理,責(zé)任主體仍是你的產(chǎn)品方。

下一步動作

  • 立即禁用生產(chǎn)環(huán)境的 Supabase MCP 插件,改用 PostgREST + 自定義函數(shù)封裝數(shù)據(jù)庫操作
  • supabase-mcp 倉庫 fork 出來,在 src/server.tshandleMcpRequest 函數(shù)里插入鑒權(quán)和 SQL 白名單邏輯
  • sqlglot 替代正則做 SQL 解析——它支持 Postgres 語法樹,能準確識別 CTE、子查詢、函數(shù)調(diào)用等復(fù)雜結(jié)構(gòu)

安全不是加個中間件,是把權(quán)限決策點放在協(xié)議入口處。MCP 的價值在于標準化,但標準化的前提是每個實現(xiàn)都守住底線。

返回首頁
邓州市| 延庆县| 盱眙县| 舒兰市| 略阳县| 原阳县| 鄂温| 太和县| 桂平市| 澳门| 蒲江县| 读书| 英山县| 正定县| 桐庐县| 巴南区| 榆中县| 西乌| 达尔| 门源| 邮箱| 鄂托克旗| 武川县| 福安市| 日照市| 津市市| 湛江市| 筠连县| 炉霍县| 江安县| 巴东县| 应城市| 缙云县| 库伦旗| 德令哈市| 陇川县| 罗甸县| 大悟县| 抚松县| 襄垣县| 易门县|