flawopen.com/Teardowns/cve-2026-14540-google-mcp-toolbox-ssrf
CVE-2026-14540:Google MCP Toolbox 服务器端请求伪造(SSRF)漏洞
CVE-2026-14540 使 MCP Toolbox 的 HTTP 请求可跟随重定向,却不检查最终网络目标。请升级至 1.5.0 或更高版本。[1], [3]
邮政分拣员检查包裹上的第一个地址,之后却不核实新地址就照着转寄标签继续投递。HTTP 重定向就像这张标签:如果服务器不检查最终 IP,原本发往普通网站的请求可能被转入内网。修复会在连接时检查实际目标,也会检查重定向目标。[2], [4], [7]
核心概念与专有名词
Server-side request forgery (SSRF)- 攻击者诱使服务向受其影响的目标发送 HTTP 请求。请求从服务器发出,因此可到达请求发起方无法访问的网络。[6]
DNS rebinding 与 TOCTOU- 主机名在验证时可能解析到一个地址,在打开 socket 时却解析到另一个地址。连接时再次检查解析出的 IP,可以弥补检查与使用之间的时间差。[2], [7]
Generic HTTP source 与 tool- MCP Toolbox 的组件根据配置的 endpoint 和工具参数构造 HTTP 请求。安全公告指出这些组件路径受影响。[1], [2], [4]
CWE-918- Server-Side Request Forgery (SSRF):应用获取 URL 或访问目标时,没有充分限制请求可以前往的位置。[6]
框架映射
- 本指南所述弱点的 CWE 参考: CWE-918
- D3-OTF 出站流量过滤 — 本指南中的出站网络限制会限制服务或主机可访问的目标。
根本原因剖析 (Root Cause)
受影响版本中的 generic HTTP source 创建 Go http.Client 时设置了 timeout 和 transport,但没有按目标限制重定向,也没有在 socket 边界检查 IP。Go 默认会跟随重定向。配置的 HTTP 工具可能把参数放入请求,因此经过构造的值或重定向能够使请求偏离预期目标。只检查原始 URL 并不够:重定向会改变目标,而且 DNS 可能在验证与连接之间返回不同 IP。上游修复增加 SSRFGuard,在 CheckRedirect 中拒绝被阻止的目标,并在连接层再次检查解析出的 IP。私有、loopback、link-local 及其他非全局地址默认被阻止;放行地址范围或私有网络属于配置例外,必须严格收窄。[1], [2], [4]
攻击执行流程分解
用三个条件判断实际可达性
这条攻击链需要同时满足三项条件:(1) 受影响的 0.3.0–1.4.0 部署使用 generic HTTP source/tool;(2) 调用方能够调用该路径,并控制 URL/路径或触发重定向;(3) Toolbox 所在主机能够路由到目标。缺少任一条件,这条链就无法通过此路径到达该目标。目标自身的身份验证和访问控制仍然有效。[1]
Toolbox 从自身网络发出请求
后续请求由 Toolbox 主机发出,可访问该主机网络允许的目标。因此,内部服务或其他可达 endpoint 可能收到 MCP 调用者无法直接发出的请求。该 CVE 并未证明每种部署都会泄露云凭据,也未证明每次重定向都会成功。[1]
源代码对比:漏洞与安全实现
这是对上游 HTTP 客户端路径的局部对比,并非完整文件替换。合并的修复加入 SSRFGuard:它检查重定向目标,并在连接时拒绝被阻止的解析 IP,从而弥补仅在重定向时解析所留下的 DNS rebinding 缺口。该 guard 默认阻止私有地址及其他非全局地址。allowPrivateNetworks、allowedIpRanges 和 customBlockedIpRanges 是影响较大的配置项;allowlist 例外应只覆盖确实需要的范围。源文件:internal/sources/http/http.go。[2]
源码摘录: HTTP 客户端与重定向策略代码摘录
client := http.Client{
Timeout: duration,
Transport: tr,
}
// 未设置 CheckRedirect 策略时,客户端会按默认策略跟随 HTTP 重定向。
// 传输层也没有针对 SSRF 目标地址的防护。
client := &http.Client{
Timeout: duration,
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 10 {
return fmt.Errorf("stopped after 10 redirects")
}
hostname := req.URL.Hostname()
if ip := net.ParseIP(hostname); ip != nil {
if guard.IsIPBlocked(ip) {
return fmt.Errorf("redirect to blocked IP %s denied", ip)
}
return nil
}
addrs, err := resolver.LookupHost(req.Context(), hostname)
if err != nil {
return fmt.Errorf("failed to resolve redirect host %s: %w", hostname, err)
}
for _, addr := range addrs {
if ip := net.ParseIP(addr); ip != nil && guard.IsIPBlocked(ip) {
return fmt.Errorf("redirect host %s resolves to blocked IP %s", hostname, addr)
}
}
return nil
},
}
// 同一个 SSRFGuard 也会在建立 socket 连接时执行,
// 因此 DNS 响应无法把允许的地址替换成被阻止的地址。
工程与系统安全加固清单
- ✓盘点 Google MCP Toolbox 二进制、容器和依赖;将 0.3.0 至 1.4.0 视为受影响版本,并升级到 1.5.0 或更高版本。[1], [3]
- ✓核实实际部署的 Toolbox 进程版本;升级 MCP 客户端、agent 框架或宿主应用不会升级此进程。[1], [3]
- ✓逐一追踪每个 generic HTTP source/tool 中哪些参数能影响 URL、路径、主机或重定向;不需要时移除不可信输入对目标地址的控制。[1], [2]
- ✓除非有记录在案的需求,否则保持
allowPrivateNetworks关闭;若启用,将allowedIpRanges限定为最小所需 CIDR,并像防火墙例外一样审查。[4], [2] - ✓使用
customBlockedIpRanges,确保敏感目标在更宽泛的私网访问获准时仍不可达。[4], [2] - ✓添加回归测试:直接访问私有和 loopback IP、主机名解析到阻止范围、重定向至阻止目标、重定向循环、无效 CIDR,以及验证与连接之间 DNS 答案改变。[2]
- ✓在主机、容器或 VPC 层实施出站网络策略,避免将来的 URL 校验回归触达 metadata 服务或无关内网。[7]
- ✓FlawOpen 响应建议:若受影响实例曾暴露,检查 HTTP 日志及网络出站中是否存在异常目标;CVE 本身不能证明数据已被访问。
参考来源
- Google CNA CVE record CVE-2026-14540 (NVD; CNA CVSS-BT 8.0, CVSS 4.0)
- Google MCP Toolbox pull request #3448: SSRF guard
- MCP Toolbox v1.5.0 release and changelog
- Google MCP Toolbox HTTP source documentation
- The Next Web: Google, JPMorgan and two governments fixed the same MCP flaw
- MITRE CWE-918: Server-Side Request Forgery (SSRF)
- OWASP SSRF 防护备忘单