Origin 校验不是身份认证:MySQL MCP Server 漏洞给 AI 平台的警告

导语

安全补丁最容易产生一种错觉:漏洞编号消失了,风险也就归零了。

CVE-2026-59971 的修复为 MySQL MCP Server 的 SSE 传输启用了 DNS Rebinding 防护,校验请求的 HostOrigin。这一步非常必要,但项目文档同时明确提示:SSE 没有内置身份认证。

这不是矛盾,而是两个不同问题:来源校验判断请求是否从允许的网络来源进入,身份认证判断调用者是谁。即使请求来自合法域名,也可能是匿名用户;即使用户已经登录,也不代表其有权调用任意 SQL 工具。

本文以该漏洞为例,为远程 MCP 服务建立"来源---身份---能力---资源"四层模型。


一、漏洞事实边界

  • mysql-mcp-server < 0.4.2 在 SSE 模式下缺少 Host/Origin 校验和路由认证。

  • 默认 stdio 传输不受公告所述网络攻击路径影响。

  • GitHub 将 CVE-2026-59971 评为 Critical,CVSS 3.1 为 10.0。

  • 修复版本 0.4.2 于 2026 年 6 月 20 日发布,开启底层 MCP SDK 的 DNS Rebinding 防护。

  • 当前文档仍说明 SSE 无内置认证,要求对外使用时置于带认证的代理之后。

  • 公告于 6 月 21 日发布,直到 9 月 11 日才进入 GitHub 已审核漏洞数据库。

  • 截至核验时没有一手来源确认在野利用;报告所述公开可达实例数量不应等同于受害者数量。


二、四层信任模型

第一层:来源

回答"请求从哪个 Host、Origin 和网络入口到达"。主要控制包括:

  • Host 允许列表;

  • Origin 允许列表;

  • 监听地址与防火墙;

  • 可信反向代理配置。

它可以降低 DNS Rebinding 和错误代理配置造成的来源混淆,但不能证明用户身份。

第二层:身份

回答"调用者是谁"。可以使用:

  • 短期访问令牌;

  • mTLS 客户端证书;

  • OIDC/OAuth 代理;

  • 企业 API Gateway 身份。

认证应覆盖会话建立与消息提交的完整路径。只保护 /sse 或只保护 /messages/ 都可能留下策略缺口。

第三层:能力

回答"这个身份可以调用哪些工具"。工具不应只有"可见/不可见"两种状态,还应区分:

  • 列出元数据;

  • 读取限定视图;

  • 修改指定数据;

  • 执行任意 SQL。

客户端显示的 destructiveHint 只是提示,不是服务端授权。

第四层:资源

回答"工具连接的后端账号最终能影响什么"。即便 MCP 层授权正确,若所有用户共享一个数据库管理员账号,后端仍无法约束越权范围。

完整判定应该是:

复制代码
allowed_source(request)
AND authenticated(identity)
AND authorized(identity, tool)
AND permitted(db_account, object, operation)

缺少任何一层,都可能把上层小失误放大为真实数据风险。


三、为什么只做 Origin 校验仍不够

假设反向代理合法域名是 mcp.example.com,升级后它已加入允许 Host。此时下面两类请求在来源层看起来相同:

复制代码
合法员工客户端 → mcp.example.com
匿名互联网客户端 → mcp.example.com

如果没有身份认证,来源校验无法区分二者。

同样,认证后的普通分析人员与数据库管理员都可能从同一域名访问:

复制代码
分析人员 → execute_sql(只读查询)
管理员 → execute_sql(维护操作)

如果工具层没有角色授权,身份认证也无法限制能力。

因此,来源校验是必要条件,不是充分条件。


四、无害访问控制模型

下面的代码不启动服务、不连接 MySQL,仅验证策略顺序:

复制代码
from dataclasses import dataclass


@dataclass(frozen=True)
class Request:
    host: str
    user: str | None
    roles: frozenset[str]


def can_call(request: Request, tool: str) -> bool:
    if request.host != "mcp.example.com":
        return False
    if request.user is None:
        return False

    policy = {
        "list_tables": {"reader", "operator"},
        "sample_table": {"reader", "operator"},
        "execute_sql": {"operator"},
    }
    return bool(request.roles & policy.get(tool, set()))


assert not can_call(Request("evil.example", None, frozenset()), "list_tables")
assert not can_call(Request("mcp.example.com", None, frozenset()), "list_tables")
assert can_call(Request("mcp.example.com", "alice", frozenset({"reader"})), "list_tables")
assert not can_call(Request("mcp.example.com", "alice", frozenset({"reader"})), "execute_sql")

这四个断言分别验证:来源非法被拒绝、匿名请求被拒绝、读者可以使用只读工具、读者不能调用高影响工具。

生产系统还应把工具参数映射到数据库对象与操作类型,不能仅在工具名称层授权。


五、补丁与剩余风险

官方补丁通过 TransportSecuritySettings 启用 DNS Rebinding 防护,并设置允许 Host。它解决了 CVE 所描述的重要根因。

但补丁没有给 SSE 增加身份体系,项目 README 明确建议:

  • SSE 进程绑定 127.0.0.1

  • 由 nginx、Caddy、Traefik 等代理提供外部入口;

  • 在代理层强制认证;

  • 正确配置转发后的 Host。

此外,补丁对缺少 transport_security 的旧 MCP SDK 采用兼容性回退。当前项目依赖范围仍允许 mcp>=1.2.0,<2,而补丁日志称相关能力需要 mcp>=1.9.0。部署方应核验运行时版本和启动日志,不能只验证顶层包版本。

这一段属于基于官方代码的工程风险分析,并非新的 CVE 结论。


六、开发与安全团队行动清单

P0:封闭匿名入口

  • 升级至 0.4.2+,优先使用当前 0.4.4

  • 非必要关闭 SSE,使用 stdio。

  • SSE 绑定 loopback,通过统一代理访问。

  • /sse/messages/ 和健康检查之外的业务路由应用一致认证。

  • 为服务身份设置短期凭据、轮换与撤销机制。

  • 删除 MCP 数据库账号的管理员权限和 FILE 权限。

P1:落实工具级授权

  • 默认不向普通身份开放任意 SQL。

  • 把只读查询封装为限定视图或固定模板。

  • 写操作使用独立角色、独立连接池和审批策略。

  • 在服务端验证角色,而不是依赖客户端隐藏工具。

  • 记录身份、会话、工具、参数摘要、数据库对象和结果状态。

P2:自动化验收

构建负向测试矩阵:

场景 预期结果
非允许 Host 拒绝
合法 Host、无身份 拒绝
合法身份、无工具权限 拒绝
只读身份发起写操作 拒绝
SDK 安全能力缺失 启动失败
代理遗漏消息路径认证 发布阻断

将这些测试放在镜像验收和部署后探测中,而不是仅靠代码审查。


七、事件排查建议

如曾运行受影响 SSE 模式,应关联三类日志:

  1. 代理或应用访问日志:Host、Origin、来源 IP、长连接和消息端点调用;

  2. MCP 审计:会话建立、工具调用、身份与拒绝原因;

  3. MySQL 审计:跨库访问、大批量读取、异常 DML、权限枚举和文件操作。

若系统过去完全没有身份日志,就无法把 SQL 操作可靠归因到具体用户。这本身就是需要整改的证据,而不是"没有发现异常"。


总结

CVE-2026-59971 的补丁告诉我们怎样拦截来源混淆;它的剩余边界则提醒我们,来源合法不代表调用者可信,身份可信也不代表拥有全部工具权限。

远程 MCP 服务的正确安全顺序应是:先验证来源,再验证身份,然后授权工具,最后由后端账号限制真实资源。任何一步依赖前一步"顺便兜底",都会在系统演进后变成漏洞。

相关推荐
小杨不想秃头1 小时前
《信息安全工程师教程(第2版)》通关笔记
安全
梦想平凡2 小时前
百游棋牌源代码开发搭建教程(五):房间创建、座位分配与请求幂等实现
前端·javascript·数据库·源代码管理
凤山老林2 小时前
Spring Boot 整合 Flowable 的企业级落地指南
数据库·spring boot·后端·flowable·工作流
企业数字化笔记2 小时前
AI写的系统出现504怎么办?接口超时和数据库慢查询排查
数据库·后端
2601_962218613 小时前
万象生鲜系统订单全生命周期状态同步技术实现业务可视
大数据·数据库·人工智能·python·算法
Wang's Blog3 小时前
Java框架快速入门:Spring Security+OAuth2之用户注册与唯一性校验实现
java·数据库·spring
workflower4 小时前
人形机器人安全伦理标准
人工智能·安全·机器学习·机器人·无人机
跨境生态圈4 小时前
2026谷歌SEO快速排名深度解析:合规起量、避坑指南与实战落地策略
数据库·人工智能·爬虫·搜索引擎·chatgpt
JavaPub-rodert4 小时前
Docker 安装 MySQL 完整教程:从零部署数据库,到生产环境持久化配置
数据库·mysql·docker