恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

MCP SSRF 连环漏洞拆解:从 Google 到 mcp-server-fetch,Agent 的信任链如何变成攻击链

  • 首页
  • 资讯中心
  • /
  • MCP SSRF 连环漏洞拆解:从 Google 到 mcp-server-fetch,Agent 的信任链如何变成攻击链

相关资讯

无线电规则2024版高效查阅指南:条款编号、频率划分与GMDSS实操 2026/10/14 1:57:49
统信服务器操作系统V20 1050a安装实战指南:从启动盘到PXE批量部署 2026/10/14 1:52:49
30 人岗位 3 秒抢完:xllg 零工报名名额并发扣减与用工单状态流转 2026/10/14 1:52:49

最新资讯

微积分概念在机器学习与AI中的应用
Cloudflare Workers AI Provider 接入(Phase 1):Kiln 后端适配与连接校验全解析
财务报表分析实战:三大报表解读与财务异常识别
CRMEB 商城系统 DAO 数据访问层深度解析:从 BaseDao 抽象基类到业务落地的分层实践
CNN特征图可视化实战:从张量处理到网格拼接的完整指南
AI Agent 面试题 053:Agent的模块化设计原则有哪些?

今日推荐

IBM Verify Identity Access 修复 22 个漏洞:两个 9.8 严重 RCE 无需认证
小区物业管理系统
小型超市仓库管理系统

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

MCP SSRF 连环漏洞拆解:从 Google 到 mcp-server-fetch,Agent 的信任链如何变成攻击链

发布时间:2026/10/14 1:57:49
MCP SSRF 连环漏洞拆解:从 Google 到 mcp-server-fetch,Agent 的信任链如何变成攻击链 2026年10月的第一周MCP生态经历了一场无声的地震。不是某个模型又刷了新榜不是某个Agent框架又多了几个star而是一组编号——CVE-2026-104120、CVE-2026-14540、CVE-2026-97228、GHSA-c9xm-49cp-xcr9——像一排钉子把Agent安全这个一直飘在PPT上的词钉进了现实。这些编号的共同点只有一个SSRF服务器端请求伪造。一个存在了二十年的老漏洞类型换了一副Agent的面孔重新登场。攻击者不再往表单里填恶意URL而是往网页、文档、工单里埋一段文字。Agent读到它把它当作正常指令转发给下一个Agent后者信任前者照做。请求就这样从内网服务器发出打向了本不该被打到的地方——数据库、元数据端点、内部管理接口。漏洞本身没有新意攻击面却是全新的。独立安全研究员Syed Anas Mohiuddin在2026年前九个月里用同一套思路在Google、Anthropic、Microsoft、Weaviate的MCP服务器中都找到了相同形状的洞。他给这类攻击起了个名字协议枢转Protocol Pivoting。攻击者通过一个协议进入利用协议之间的信任假设在另一个协议上拿到本不该有的能力。10月6日The Next Web报道JPMorgan Chase、法国政府跨部门数字管理局DINUM、印尼丹格朗市政府也修复了同类问题而美国总务管理局技术转型服务处的五个MCP服务器仍在分诊中。这篇文章不打算罗列新闻标题。我们拆开看三个最具代表性的漏洞实例——Google mcp-toolbox的8.0分缺陷、mcp-server-fetch那个存在却从未被调用的守卫函数、以及rmcp客户端的OAuth元数据SSRF——然后给出一份可以直接抄进生产环境的防御清单。每一个案例都会落到具体的代码路径和修复提交上不停留在尽快升级这种正确的废话上。在展开之前有必要先对齐一个背景认知MCPModel Context Protocol从2024年11月Anthropic首次发布到现在只经过了不到两年时间。但到2026年10月OX Security的一份普查报告已经在公网上数出了15465个活跃的MCP服务器实例其中2.3%的主机名已经不再解析6个过期域名可以被任何人以每年4到12美元的价格重新注册。15.6%的主机名解析到了美国境外的基础设施上包括位于中国和俄罗斯的主机。协议成熟的速度远远超过了围绕它的注册卫生和治理能力。攻击面解剖信任链上的三个断层MCP的设计初衷是让AI应用和Agent之间有一个标准化的通信协议。2026年7月28日发布的无状态规范进一步简化了部署——不再需要会话握手不再需要Mcp-Session-Id每个请求自包含、可独立路由。这解决了扩展性问题但也把一个老问题推到了更显眼的位置当Agent A通过MCP把任务委托给Agent BAgent B凭什么相信A答案在当前的MCP实现里是默认信任。MCP服务器为每个Agent存储凭据Agent被设计为信任内部网络中的每一个其他Agent。这种信任模型在单机时代或许够用但在多Agent协作的架构里它创造了一条攻击者可以走过的信任链。断层出现在三个位置。第一服务端Agent替服务器发请求。一个Agent收到包含恶意URL的任务调用MCP服务器上的工具去抓取或请求该URL。服务器没有验证目标地址是否安全直接发出请求。SSRF就这样从Agent的手变成了服务器的口。第二客户端OAuth元数据发现变成了SSRF通道。MCP客户端在OAuth流程中会从服务器返回的WWW-Authenticate头里读取resource_metadata URL并发起请求。如果这个URL指向内网地址或云元数据端点客户端就会从受害者网络内部发出请求。第三运行时Agent的执行角色权限过大。即使Agent本身没有被直接攻击只要它能访问实例元数据服务IMDS攻击者就能通过提示注入让Agent去请求169.254.169.254拿到临时凭据再用这些凭据从外部访问整个AWS账户。Rapid7的漏洞情报总监Douglas McKee说得很直白AI Agent给了攻击者一组全新的连接可以走。有人种一段文字一个Agent读到它把它当作正常的委托任务传给另一个Agent后者因为信任前者而执行。链条上的每一环都完全按设计运行这正是它难以捕捉的原因。CVE-2026-14540Google mcp-toolbox的8.0分HTTP客户端缺陷Google的MCP Toolbox for Databases是一个让Agent直接查询数据库的工具集版本0.3.0到1.4.0的通用HTTP源在初始化HTTP客户端时犯了一个教科书级的错误没有设置CheckRedirect策略也没有验证目标IP地址。CheckRedirect策略控制服务器在遇到HTTP重定向时的行为。没有这个策略一个精心构造的路径参数就能让工具箱跟随重定向跳到内部端点代表攻击者发出请求。Mohiuddin的解释是Google的修复涉及应用IP范围允许列表和阻止列表。它在启动时而不是首次请求时拒绝不安全的基URL。这才是真正的SSRF守卫应该有的样子。这也是大多数MCP服务器还没做的工作。修复方案是googleapis/mcp-toolbox的PR #3448随v1.5.0发布。核心变化是在HTTP客户端初始化时注入一个重定向检查钩子每次重定向都会验证目标地址是否在允许范围内。如果不在请求在启动阶段就被拒绝而不是等到连接已经建立。这个漏洞在CVSS 4.0下拿到8.0分High原因是它的利用条件极低——不需要认证不需要用户交互只需要让Agent读到一段包含恶意URL的文字。在Agent架构里这段文字可以出现在任何地方一个网页、一封邮件、一份PDF、一个工单的描述字段。CVE-2026-104120守卫函数存在但从未被调用mcp-server-fetch是MCP官方参考实现中的抓取服务器几乎所有用MCP做过网页抓取的开发者都直接或间接用过它。CVE-2026-104120描述了fetch_url函数中的SSRF漏洞CVSS 3.1评分7.3HighCVSS 4.0评分6.9Medium。漏洞影响2026.6.4及之前版本而2026.7.10和2026.8.18两个后续版本在修复合入前就已经发布同样存在漏洞。CVE记录在10月6日最后更新时仍然写着修复PR等待接受指向的是已被关闭未合并的PR #4890而不是实际合并的PR #5033。版本范围也停留在2026.6.4没有覆盖到后续版本。如果你依赖CVE记录来判断自己是否暴露这个记录会给你一个错误的答案。真正值得深思的是Mohiuddin在他的分析中揭示的一个细节mcp-server-fetch代码库里其实已经有一个守卫函数check_may_autonomously_fetch_url()但提示处理器直接调用了fetch函数从未调用这个守卫。一个存在于某条代码路径上但不在另一条上的守卫不是守卫。修复在10月5日合入modelcontextprotocol/servers仓库的v2/main分支关闭issue #4838。PR #5033从9月28日社区提交的PR #4890移植而来核心改动是一个请求钩子在服务器发出每个请求之前——包括robots.txt检查、页面抓取和每一次重定向跳转——先解析主机名如果任何解析结果不是公开可路由地址拒绝请求。拒绝的集合包括回环地址、RFC 1918私有范围、169.254.0.0/16链路本地段各大云厂商的元数据端点都在这里以及其他IANA特殊用途范围。维护者特意把开关做成了一个命令行标志--allow-private-ips而不是可以通过工具参数传递的配置项。原因很直接这样调用工具的模型就不能把它关掉。修复随mcp-server-fetch 2026.10.10发布在PyPI上。但它有两个已知限制DNS重绑定窗口在检查和连接之间仍然存在服务器无法自己解析的主机名会被放行。这意味着DNS重绑定攻击在理论上仍然可能只是窗口被大大压缩了。客户端也有份rmcp的OAuth元数据SSRFSSRF不只是服务器的问题。GitHub安全公告GHSA-c9xm-49cp-xcr9描述了rmcp——Rust语言的MCP SDK——中的一个OAuth客户端漏洞。该客户端在处理OAuth授权流程时会从服务器返回的WWW-Authenticate头中读取resource_metadata URL然后不加验证地发起请求。这个URL可以指向localhost、私有IP范围或云元数据端点客户端就会从受害者的网络内部发出请求。这个漏洞影响rmcp 1.8.0及以下版本2.0.0已修复。攻击场景很直接一个恶意MCP服务器在OAuth握手阶段返回一个指向内网的resource_metadata URL客户端照做内网请求就这样被发了出去。MCP官方安全最佳实践指南在2026-07-28规范中有专门的SSRF章节覆盖了完全相同的流程。它建议对OAuth相关URL强制HTTPS、阻止私有和链路本地范围、验证每个重定向目标、使用出口代理并警告DNS检查时与使用时之间的间隙。指南还特别提醒避免手动实现IP验证。AgentCorruption当IMDS变成凭据提款机10月8日Zenity Labs在多伦多SecTor大会上披露了AgentCorruption。这不是MCP协议的漏洞但它和MCP SSRF共享同一个形状一个模型选择的请求到达了内部端点Agent的身份决定了后果有多严重。Zenity的技术报告称一个配备了出站HTTP工具的测试Agent被提示请求实例元数据端点169.254.169.254并成功中转了其执行角色的临时凭据。研究人员随后从AgentCore外部使用了这些凭据。默认执行角色的权限延伸到同一AWS账户和区域中的其他AgentZenity还通过其他工具包括shell工具复现了元数据访问。时间线值得注意Zenity在2025年12月25日报告了元数据问题。AWS回应称自2026年2月14日起新部署的AgentCore Agent仅使用IMDSv2。Zenity的新闻稿补充说其测试确认AWS已缩减默认执行角色的权限包括移除了让Agent调用其他Agent、读取私有对话或访问AWS Secrets Manager中秘密的权限。AWS对定性有异议其声明称所描述的行为是记录在案且符合预期的并建议客户仅授予其执行角色Agent所需的权限。AWS的回应措辞很能说明问题。当一个安全研究员花了近一年时间追踪的漏洞被厂商定性为记录在案且符合预期时潜台词是我们知道这个风险存在我们认为这是配置问题而不是产品缺陷。从安全工程的角度看这种分类方式把责任推给了用户——但默认配置的安全水位恰恰决定了大多数用户的实际安全水位。不是每个使用AgentCore的团队都有安全工程师会去审计IAM角色的权限边界。防御清单从零信任到出口代理把上面所有案例的修复方案提炼成一份可操作的清单核心原则只有一条零信任。假设你的Agent、你的MCP服务器、你的客户端、你的运行时环境中至少有一个已经被感染了然后设计它们之间的每一次交互。1. 在网络层强制执行出口控制。把Agent和MCP服务器放在出口代理或网络策略后面默认拒绝私有、回环和链路本地目标。MCP规范指向了Smokescreen这样的出口代理。代码内检查仍然有缝隙——fetch服务器自己记录的DNS重绑定限制就是证据。2. 用经过审计的库而不是手写IP验证。MCP安全最佳实践明确警告不要手动实现IP验证。用你所用语言中维护良好的SSRF防护库确保它们处理IPv6、DNS重绑定和重定向链。3. 收敛Agent权限。给你的Agent执行角色最小必要权限。如果一个Agent不需要调用其他Agent就移除这个权限。如果它不需要读Secrets Manager就不给它这个权限。AWS对AgentCorruption的回应虽然措辞强硬但这条建议本身是对的。4. 加固元数据服务。在AWS上强制IMDSv2——它需要一个通过PUT请求获取的会话令牌比IMDSv1的GET请求难伪造得多。其他云厂商有类似的加固方案确保你的Agent运行环境已经启用。5. 把LLM输出当作不可信输入。McKee的教训值得再引一次从LLM传给你的工具的任何东西都应该被当作来自互联网上陌生人的输入来对待因为在提示注入场景中它就是。6. 升级你的mcp-server-fetch。如果你运行MCP官方参考实现中的fetch服务器立即升级到2026.10.10或更高版本。检查你的部署管道中是否固定了旧版本号Docker镜像也需要重新构建。不要依赖CVE记录的版本范围来判断自己是否暴露——截至10月11日CVE-2026-104120的记录仍然没有反映已合并的修复。7. 审计你的Agent能看到什么。一次完整的安全审计应该列出每个Agent可以访问的所有URL、所有工具、所有其他Agent。如果一个Agent只需要调用天气API它就不应该能访问数据库工具。职责分离和最小权限原则在Agent架构中同样适用甚至更加重要——因为Agent的行为路径比人类操作员更难预测。审计的频率也应该跟上部署的速度——每个季度一次是底线每个月一次才是目标。代码实战用Python构建一个MCP工具级别的SSRF防护钩子下面这个示例展示如何在一个基于Python的MCP工具服务器中集成SSRF防护。它实现了PR #5033的核心逻辑在每个出站请求前解析主机名、检查IP范围、验证每个重定向跳转。代码可以直接嵌入任何使用requests或httpx的MCP服务器中。我们用一个GuardedFetcher类来封装所有出站HTTP调用。每次调用前它先通过socket.getaddrinfo解析目标主机名检查每一个解析结果是否落在禁止的IP范围内。如果任何一步解析失败或命中黑名单请求在发出前就被拒绝。import socket import ipaddress import requests from urllib.parse import urlparse from typing import Optional, Set class SSRFGuard: MCP工具级SSRF防护解析-检查-执行三段式 # 禁止的IP范围回环、私有、链路本地、元数据端点等 BLOCKED_RANGES [ ipaddress.ip_network(127.0.0.0/8), # 回环 ipaddress.ip_network(10.0.0.0/8), # RFC 1918 ipaddress.ip_network(172.16.0.0/12), # RFC 1918 ipaddress.ip_network(192.168.0.0/16), # RFC 1918 ipaddress.ip_network(169.254.0.0/16), # 链路本地 云元数据 ipaddress.ip_network(100.64.0.0/10), # CGNAT ipaddress.ip_network(198.18.0.0/15), # 基准测试 ipaddress.ip_network(224.0.0.0/4), # 组播 ipaddress.ip_network(240.0.0.0/4), # 保留 ipaddress.ip_network(::1/128), # IPv6 回环 ipaddress.ip_network(fc00::/7), # IPv6 ULA ipaddress.ip_network(fe80::/10), # IPv6 链路本地 ipaddress.ip_network(ff00::/8), # IPv6 组播 ] # 允许的协议 ALLOWED_SCHEMES: Set[str] {http, https} # 允许的主机名白名单可选优先级高于黑名单 ALLOWED_HOSTS: Set[str] set() def __init__(self, allow_private_ips: bool False): self.allow_private_ips allow_private_ips def _is_blocked_ip(self, ip_str: str) - bool: 检查IP是否在禁止范围内 try: addr ipaddress.ip_address(ip_str) for network in self.BLOCKED_RANGES: if addr in network: return True return False except ValueError: # 无法解析为IP视为可疑 return True def _resolve_and_check(self, hostname: str) - bool: 解析主机名并检查所有解析结果。 返回True表示安全False表示应拒绝。 if hostname in self.ALLOWED_HOSTS: return True try: # 获取所有地址族IPv4 IPv6的解析结果 results socket.getaddrinfo( hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM ) except socket.gaierror: # 解析失败主机名不存在或DNS错误 # 按PR #5033的设计无法解析的主机名放行 # 因为DNS重绑定利用的是解析和连接之间的窗口 return True for family, _, _, _, sockaddr in results: ip_str sockaddr[0] if self._is_blocked_ip(ip_str): return False return True def check_url(self, url: str) - tuple[bool, Optional[str]]: 检查URL是否安全。 返回 (is_safe, reason)。is_safeFalse时应拒绝请求。 parsed urlparse(url) # 协议检查 if parsed.scheme.lower() not in self.ALLOWED_SCHEMES: return False, f协议不允许: {parsed.scheme} hostname parsed.hostname if not hostname: return False, 无法提取主机名 # 直接IP地址检查绕过DNS解析 try: ipaddress.ip_address(hostname) # 是纯IP直接检查 if self._is_blocked_ip(hostname): return False, f目标IP在禁止范围内: {hostname} return True, None except ValueError: pass # 不是IP是主机名走DNS解析 # DNS解析 检查 if not self._resolve_and_check(hostname): return False, f主机名解析到禁止IP: {hostname} return True, None def safe_request(self, url: str, method: str GET, max_redirects: int 5, **kwargs) - requests.Response: 带SSRF防护的HTTP请求。 每次重定向都会重新检查目标地址。 current_url url for redirect_count in range(max_redirects 1): # 每次请求/重定向前都检查 is_safe, reason self.check_url(current_url) if not is_safe: raise SSRFBlockedError( fSSRF防护拦截: {reason} (URL: {current_url}) ) # 禁止自动跟随重定向手动处理 kwargs[allow_redirects] False resp requests.request(method, current_url, **kwargs) if resp.is_redirect: location resp.headers.get(Location) if not location: break # 处理相对重定向 current_url requests.compat.urljoin(current_url, location) continue else: return resp raise SSRFBlockedError( f超过最大重定向次数 ({max_redirects}): {url} ) class SSRFBlockedError(Exception): SSRF防护拦截异常 pass # --- 使用示例在MCP工具服务器中集成 --- def create_mcp_fetch_tool(guard: SSRFGuard): 创建一个带SSRF防护的MCP fetch工具 async def fetch_url(url: str) - str: MCP工具函数抓取指定URL的内容 try: resp guard.safe_request(url, timeout10) return resp.text[:5000] # 截断防止内存溢出 except SSRFBlockedError as e: return f请求被安全策略拦截: {e} except requests.RequestException as e: return f请求失败: {e} return fetch_url # 初始化生产环境 guard SSRFGuard(allow_private_ipsFalse) fetch_tool create_mcp_fetch_tool(guard) # 测试 if __name__ __main__: # 这些应该被拦截 test_urls [ http://169.254.169.254/latest/meta-data/, # AWS元数据 http://localhost:8080/admin, # 回环 http://192.168.1.1/router/setup, # 私有IP http://[::1]:3000/internal, # IPv6回环 ftp://internal-server/data, # 协议不允许 ] print( SSRF防护测试 ) for test_url in test_urls: is_safe, reason guard.check_url(test_url) status ✓ 放行 if is_safe else f✗ 拦截 ({reason}) print(f {test_url}) print(f → {status}) # 这些应该放行 safe_urls [ https://api.github.com/repos/modelcontextprotocol/servers, https://pypi.org/pypi/mcp-server-fetch/json, ] print(\n 正常请求测试 ) for safe_url in safe_urls: is_safe, reason guard.check_url(safe_url) status ✓ 放行 if is_safe else f✗ 拦截 ({reason}) print(f {safe_url}) print(f → {status})运行这个测试脚本你会看到所有指向内网、元数据端点和非HTTP协议的URL都被拦截而正常的公网API请求被放行。关键设计点有三个第一每个请求和每次重定向前都重新解析和检查而不是只在第一次第二阻止列表覆盖了IPv4和IPv6的所有危险范围第三allow_private_ips是一个启动时的配置项不是运行时的参数模型无法通过工具调用来关闭它。这个实现还有一个已知的限制DNS重绑定。攻击者可以控制一个域名在防护检查时解析到一个公网IP在实际连接时解析到内网IP。缓解这个风险需要在连接层做第二次检查——在TCP连接建立后、发送HTTP请求前验证实际连接的远端IP仍然安全。这超出了应用层代码的范围需要在网络栈或出口代理层面解决。协议层的修复方向MCP 2026-07-28规范在安全方面已经做了不少工作发行者验证RFC 9207、资源指示器RFC 8707、完整JSON Schema 2020-12支持。但SSRF暴露出的是一个更根本的问题——MCP的信任模型假设内部网络中的Agent彼此可信而现实是任何一个Agent都可能成为攻击的跳板。短期内最有效的防御是网络层出口控制加上每个MCP服务器自己的SSRF防护。中期来看MCP规范可能需要引入Agent身份验证和授权的标准机制让Agent A委托Agent B这个行为本身就需要经过授权而不是默认信任。长期方向是把零信任原则嵌入协议设计——每个请求都携带可验证的身份声明每个服务器都验证调用者是否有权请求目标资源。10月11日发布的mcp-server-fetch 2026.10.10和modelcontextprotocol/servers v1.0.0版本标志着MCP官方安全响应的第一个重要里程碑。PR #5033的合入过程也暴露了一个治理问题社区在9月28日就提交了功能相同的PR #4890但被关闭未合并直到10月5日维护者才以另一个PR合入了移植版本。对于安全修复来说这一周的时间差不是小事——在此期间任何阅读了issue #4838的人都知道漏洞在哪里但官方版本仍然没有修复。数字本身也在讲述一个故事。Mohiuddin测试了来自Google、JPMorgan Chase、Weaviate、Rapid7、法国DINUM和美国联邦政府六个不同组织的Agent它们唯一的共同点就是使用MCP。五个组织确认了漏洞并修复了它。Rapid7的CVE-2026-97228评分只有2.7属于低危Google的CVE-2026-14540评分8.0属于高危。同一个协议同一个攻击思路危害等级却相差三倍——这说明风险不只取决于协议本身更取决于每个实现者在HTTP客户端初始化时做了什么和没做什么。X41 D-Sec的研究员Markus Vervier说得对——这本质上还是间接提示注入。但Mohiuddin给它起的名字协议枢转有价值因为它指出了一个被忽视的事实当Agent架构跨越多个协议时信任和授权在协议边界处丢失了。一个协议检查前门另一个协议检查后门没有人看守走廊。十月的第一周不是终点。随着Agent架构在企业中的部署密度持续增加类似的漏洞还会冒出来。但至少现在我们知道了攻击者会走哪条路也知道该在哪里设卡。如果你正在运行任何MCP服务器今天就检查你的版本号。如果你在写新的MCP工具把SSRF防护当作第一个功能来实现而不是第一个补丁。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号