我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 97.1% 的成绩。 了解更多

深度解析

深度解析

Echo WebSocket 代理身份验证绕过(GHSA-cxf3-9h37-7rr8)

Echo 的 Proxy 中间件在 WebSocket 升级被拒绝后,仍保留通往上游的原始隧道;该连接上的后续 HTTP 请求跳过 Echo 路由器和路由中间件,从而绕过仅在 Echo 路由上实施的身份验证。GitHub Advisory Database 将其评为严重,CVSS v4.0 9.1;Echo 自身公告则评为中危。2026 年 10 月 22 日发布的 v4.16.1 和 v5.4.1 已修复。目前尚无已知的公开概念验证或在野利用。

要点速览

  • 当客户端请求对由 Echo Proxy 中间件处理的路由进行 WebSocket 升级时,旧版本会接管客户端连接,直接连接上游,双向复制字节,却从不读取上游响应。如果上游用普通 HTTP 响应拒绝升级并保持连接,隧道就会持续开放。
  • 攻击者在同一连接上发送的后续 HTTP 请求会直接转发至上游,因此大多数应用实施身份验证和授权的 Echo 路由器及路由中间件完全看不到这些请求。
  • GitHub Advisory Database 的评审将此问题评为严重,CVSS v4.0 9.1;Echo 维护者将自身公告评为中危。记录的分类为 CWE-444 和 CWE-863。截至 2026 年 10 月 24 日,该问题未列入 KEV 目录,没有公开漏洞利用代码,也没有已知在野利用。
  • v4 分支升级至 v4.16.1 或更高版本,v5 分支升级至 v5.4.1 或更高版本。在此之前,应在 WebSocket 升级请求到达代理路由前拒绝它,或在上游独立实施授权。

我是否受到影响?

如果以下条件全部成立,您就受到影响:

  • 应用或 API 网关使用 Echo,模块 github.com/labstack/echo/v4 为 4.16.0 或更早版本,或 github.com/labstack/echo/v5 为 5.4.0 或更早版本。
  • 某个路由或路由组使用 Echo 内置的 Proxy 中间件(middleware.Proxy、ProxyWithConfig 或负载均衡辅助函数),由 Echo 将请求转发给上游。
  • 客户端可以访问该代理路由,并请求 WebSocket 升级。
  • 上游资源的安全检查位于 Echo 路由或中间件中,而不是上游本身。

如果您从未挂载 Proxy 中间件,就不受影响:普通 Echo 路由、身份验证中间件、静态文件服务等不属于此漏洞范围。该绕过也不能让攻击者访问代理配置的上游以外的主机,更不能击败上游自身的身份验证。pkg.go.dev 列出 32,160 个导入 github.com/labstack/echo/v4 的包(于 2026 年 10 月 24 日核查),其中只有挂载 Proxy 中间件的子集存在暴露。

分支 受影响版本 修复版本
echo/v4 >= 4.0.0, < 4.16.1 4.16.1
echo/v5 >= 5.0.0, < 5.4.1 5.4.1

公告指出,运行时复现已确认 v4.15.0、v4.16.0、v5.0.0 和 v5.4.0 受到影响,而源码历史显示这种缺失验证的问题可追溯至 v4.0.0。

检查模块及其版本:

go list -m github.com/labstack/echo/v4
go list -m all | grep labstack/echo
govulncheck ./...
# In a Docker image that has the module cache
docker run --rm <image> sh -c "go list -m github.com/labstack/echo/v4 2>/dev/null || grep labstack/echo /go.mod"

# Directly in the build files
grep -rn "labstack/echo" go.mod go.sum

当受影响模块位于构建依赖图中时,govulncheck 会根据该公告标记对应的版本范围。

如何修复?

升级模块:

go get github.com/labstack/echo/v4@v4.16.1
# or, on the v5 line
go get github.com/labstack/echo/v5@v5.4.1
go mod tidy

注意 v4.16.1 的发布要求:修补后的 golang.org/x/ 依赖需要 Go 1.26 或更高版本,因此构建工具链可能也需更新。后续补丁版本,例如 2026 年 10 月 23 日发布的 v4.16.2,包含同一修复及后续改进,因此固定到当前分支的最新补丁版本也可以。

如果暂时无法升级,公告给出了两种临时措施,并强调了一种无效做法:

  • 在 WebSocket 升级请求到达受影响代理路由前拒绝它。在代理前添加一个简单中间件,对升级尝试返回普通错误,即可封闭入口。
  • 在每个上游资源上独立实施授权,使绕过 Echo 路由层的请求仍然接受实际检查。
  • 仅让上游返回非 101 响应没有帮助,因为正是这种拒绝导致存在漏洞的隧道持续开放。

其局限很直接:第一种措施完全禁用 WebSocket 代理;第二种只保护具有独立检查的资源,需要应用逐个资源验证。

根本原因是什么?

Echo 的 Proxy 中间件在检查上游是否接受升级之前,就为 WebSocket 请求选择了原始字节隧道,因此即使上游拒绝,隧道仍继续运行。

v4.16.0 的 middleware/proxy.go 第 391 行中的分发逻辑:

// Proxy
switch {
case c.IsWebSocket():
    proxyRaw(tgt, c, config).ServeHTTP(res, req)
default: // even SSE requests
    proxyHTTP(tgt, c, config).ServeHTTP(res, req)
}

问题位于 proxyRaw(第 134 行)。它接管客户端连接,连接上游,并双向复制字节:

in, _, err := c.Response().Hijack()
...
out, err := dialFunc(c.Request().Context(), "tcp", t.URL.Host)
...
// Write header
err = r.Write(out)
...
errCh := make(chan error, 2)
cp := func(dst io.Writer, src io.Reader) {
    _, copyErr := io.Copy(dst, src)
    errCh <- copyErr
}

go cp(out, in)
go cp(in, out)

注意缺失的环节:r.Write(out) 发送升级请求后,两个 io.Copy 循环就持续搬运字节,但没有任何逻辑读取上游对升级请求的 HTTP 响应,也没有将隧道建立的条件限定为上游返回 101 Switching Protocols。相比之下,非 WebSocket 分支 proxyHTTP 委托给 Go 的 httputil.NewSingleHostReverseProxy,该组件确实会验证上游响应。

后果由此直接产生。客户端连接一旦被接管,Echo 对该连接的请求处理就结束了。如果上游以普通 HTTP 响应答复升级尝试,并且关键的是通过 HTTP keep-alive 保持 TCP 连接,原始复制循环就会继续转发。客户端收到上游拒绝响应的字节后,可以在同一连接上发送另一个普通 HTTP 请求。cp(out, in) 将它原样写入上游,上游响应也沿同一路径返回。这些请求绕过了 Echo 的路由器、路由中间件、速率限制和路由级身份验证,因为在 Echo 看来,连接在被接管时已经离开 HTTP 处理流程。

如何利用?

目前没有公开的概念验证。维护者 vishr 发布的公告向报告者 @Duodum 致谢,描述了机制,并表示维护者已在 v4.15.0、v4.16.0、v5.0.0 和 v5.4.0 上完成运行时复现。公告描述的攻击路径如下:

  1. 攻击者连接到使用 Proxy 中间件的 Echo 路由,并发送带有 WebSocket 升级请求头的 HTTP 请求。
  2. Echo 接管客户端连接,并向配置的上游请求升级。
  3. 上游没有在该路径监听 WebSocket,或拒绝升级,并在保持开放的连接上返回普通 HTTP 响应,例如 200 或 404。
  4. 原始复制循环继续运行,因此攻击者获得了一条 Echo 不再检查的持久上游通道。
  5. 攻击者向该通道写入普通 HTTP 请求。每个请求都逐字节转发给上游,每个响应都直接返回。
  6. 上游提供的任何没有独立授权检查的路径或资源此时都可访问,即使对应请求原本需要通过 Echo 路由的身份验证。

此链条中的每个条件都至关重要:可访问的代理路由、拒绝升级后不关闭连接的上游,以及信任代理入口检查的上游资源。

攻击流程

flowchart LR A["攻击者向代理路由发送 WebSocket
升级请求"] --> B["Echo 选择 proxyRaw 并
接管客户端连接"] B --> C["将原始请求写入上游,
从不读取上游响应"] C --> D["上游用普通 HTTP 拒绝升级
并保持连接"] D --> E["隧道继续复制字节,
缺少升级检查"] E --> F["攻击者在同一连接上
发送普通 HTTP 请求"] F --> G["原样转发至上游,
跳过 Echo 路由器和中间件"] G --> H["返回未受保护的上游资源,
绕过路由身份验证"]

攻击者能做什么?

攻击者以未通过身份验证的客户端权限,访问配置的上游中原本由 Echo 路由层保护的资源。影响取决于这些资源在没有独立检查时暴露了什么:内部端点、无需身份验证的服务,以及被认为受代理路由中间件保护的管理面板。公告规定的边界如下:

  • 无法代理到任意主机。隧道只通向代理配置的上游,因此它不是开放代理。
  • 上游存在自身身份验证时,该验证仍然有效。
  • 需要可访问的代理路由,且上游必须在拒绝升级后保持连接。
  • 除了能通过网络访问该路由外,不需要身份验证、用户交互或特权位置。

据此可以合理概括:在 Echo 层实施身份验证,并依赖上游位于其后、不可直接访问或无需验证的部署,才真正面临风险。这也是两个严重程度评级分歧的核心。

为什么修复有效?

补丁彻底移除 proxyRaw,让所有请求,无论是否为 WebSocket,都经过 Go 反向代理。v4 修复提交如下:

-                // Proxy
-                switch {
-                case c.IsWebSocket():
-                    proxyRaw(tgt, c, config).ServeHTTP(res, req)
-                default: // even SSE requests
-                    proxyHTTP(tgt, c, config).ServeHTTP(res, req)
-                }
+                // ReverseProxy validates upgrades and closes both sides when a tunnel ends.
+                proxyHTTP(tgt, c, config).ServeHTTP(res, req)

proxyHTTP 现在会将目标协议 ws、wss 规范化为 http、https,并委托给 httputil.NewSingleHostReverseProxy,在正式切换前读取上游响应:只有收到有效的 101 Switching Protocols 响应后才进入隧道;升级被拒绝时,则按原本的普通 HTTP 响应转发。正如发布说明所述,拒绝升级不再留下绕过 Echo 路由和路由中间件的原始隧道。

该修复在中间件层面完整解决了此问题:Proxy 中不再有任何路径会在升级未获接受时进入隧道;补丁还会在任意一端断开时关闭两端连接,这对应关联公告 GHSA-9969-6676-49h5。修复并不会为上游添加身份验证;此前没有独立检查的资源,对于正确路由、已通过身份验证的流量,仍保持原有的开放程度。

如何检查是否已遭入侵?

该问题没有已发布的入侵指标,Echo 也未列出任何指标。攻击者在日志中留下的请求模式具有辨识度,因此您可以检查自己的日志:

  • 对代理路由建立的连接带有 WebSocket 升级请求头 Connection: Upgrade 和 Upgrade: websocket,并在上游返回非 101 响应后仍承载 HTTP 流量。
  • 上游在同一个长期连接上记录了多个普通 HTTP 请求,而前端代理并未记录同一流量对应的路由请求。
  • 上游访问记录显示请求触及本应由 Echo 路由层限制访问的资源。

如果上游日志包含资源路径,代理日志包含已路由的路径,同一客户端连接的两者不匹配就是需要调查的信号。

时间线

  • 2026-10-22:Echo 发布包含修复的 v4.16.1 和 v5.4.1,维护者 vishr 发布公告 GHSA-cxf3-9h37-7rr8,将其评为中危并向 @Duodum 致谢。
  • 2026-10-22:v4.16.1 和 v5.4.1 的发布说明描述了新的验证机制及关联安全修复。
  • 2026-10-23:GitHub Advisory Database 发布经评审的公告,将其评为严重,CVSS v4.0 9.1,分类为 CWE-444 和 CWE-863。Echo 发布 v4.16.2,进一步加固 v4 分支。
  • 2026-10-24:本文发布。

常见问题

为什么严重程度评级不一致?

GitHub Advisory Database 的评审评分为 CVSS v4.0 9.1、严重,并标注存在攻击前提条件;Echo 自身公告页面则标为中危,未公布分数。分歧与前提条件有关:攻击需要代理路由、拒绝升级后不关闭连接的上游,以及没有独立检查的上游资源。满足这些条件时,公告数据库的评分认为路由级安全边界被完全击穿,修复的紧迫性也由此而来。

这会把我的服务器变成开放代理吗?

不会。隧道仅连接 Proxy 中间件配置的转发上游,公告明确指出该问题不提供任意主机代理能力。暴露的是您自己的上游资源,而非第三方目标。

它会绕过上游自身的身份验证吗?

不会。上游自身的身份验证机制与之前完全一样。被绕过的是仅存在于 Echo 路由和中间件中的控制,因此公告建议在上游本身实施授权作为临时措施。

我的服务不使用 Echo Proxy 中间件,是否受影响?

不受影响。漏洞位于 Proxy 中间件的原始 WebSocket 路径。使用 Echo 进行路由、静态文件服务或运行自定义处理器,但未挂载代理的应用,不会执行这条代码路径。

v4.16.1 和 v5.4.1 还包含哪些修复?

两个版本还包含数据库中评级为高危的三项关联公告:GHSA-9969-6676-49h5,客户端断开后 WebSocket 代理连接仍被保留;GHSA-h7wr-284f-5qvc,v4 Decompress 中间件中的无限制 gzip 解压;以及 GHSA-f48p-c9v4-h7xv,v4 中无限制的 BodyDump 捕获。为 WebSocket 修复升级时,这些问题也会一并解决。

使用 Ostorlab 扫描 Go 服务和容器镜像,识别其包含的 Echo 模块版本,并标记仍使用 v4.16.0、v5.4.0 或更早版本的部署。

参考资料

  • Echo 公告 GHSA-cxf3-9h37-7rr8,厂商评级为中危,2026 年 10 月 22 日发布,向 @Duodum 致谢:https://github.com/labstack/echo/security/advisories/GHSA-cxf3-9h37-7rr8 (2026 年 10 月 24 日核查)
  • GitHub Advisory Database 评审,严重,CVSS v4.0 9.1,CWE-444 和 CWE-863:https://github.com/advisories/GHSA-cxf3-9h37-7rr8 (2026 年 10 月 24 日核查)
  • v4 分支修复提交 3fb0ba7e:https://github.com/labstack/echo/commit/3fb0ba7e17645bb65611e2a08875d0a2f65c421f (2026 年 10 月 24 日核查)
  • v5 分支修复提交 1855061e:https://github.com/labstack/echo/commit/1855061e572ae9dab727c811d8382f266bfbaaec (2026 年 10 月 24 日核查)
  • v4.16.1 发布说明,2026 年 10 月 22 日发布,包含 Go 1.26 要求和关联修复:https://github.com/labstack/echo/releases/tag/v4.16.1 (2026 年 10 月 24 日核查)
  • v5.4.1 发布说明,2026 年 10 月 22 日发布:https://github.com/labstack/echo/releases/tag/v5.4.1 (2026 年 10 月 24 日核查)
  • v4.16.2 发布说明,2026 年 10 月 23 日发布:https://github.com/labstack/echo/releases/tag/v4.16.2 (2026 年 10 月 24 日核查)
  • v4.16.0 中存在漏洞的 proxy.go 源码:https://raw.githubusercontent.com/labstack/echo/v4.16.0/middleware/proxy.go (2026 年 10 月 24 日核查)
  • pkg.go.dev 上 echo/v4 的导入者数量,32,160 个包:https://pkg.go.dev/github.com/labstack/echo/v4 (2026 年 10 月 24 日核查)
  • 关联公告 GHSA-9969-6676-49h5:https://github.com/advisories/GHSA-9969-6676-49h5 (2026 年 10 月 24 日核查)
  • 关联公告 GHSA-h7wr-284f-5qvc:https://github.com/advisories/GHSA-h7wr-284f-5qvc (2026 年 10 月 24 日核查)
  • 关联公告 GHSA-f48p-c9v4-h7xv:https://github.com/advisories/GHSA-f48p-c9v4-h7xv (2026 年 10 月 24 日核查)