Netty 4.2.15.Final:两个高危 CVE 修复,你的服务可能正在暴露

2026-06-03 29 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:8 分钟

Netty 4.2.15.Final 刚刚发布,这不是一个功能迭代版本——它只做了一件事:堵住正在被利用的安全漏洞。其中两个高危 CVE 分别涉及 HAProxy 协议解码器的内存耗尽攻击和 DNS 解析器的缓存中毒,影响范围远比想象中大。如果你在用 Netty 做网关、Sidecar 代理或任何涉及 DNS 解析的服务,这个版本需要立刻进入升级计划。

CVE-2026-48059:HAProxy 解码器可以被喂到内存撑爆

netty-codec-haproxy 模块负责解析 HAProxy PROXY 协议,常用于 L4/L7 代理场景——比如你的服务跑在 HAProxy 或 Envoy 后面,通过 PROXY 协议拿到真实客户端 IP。

问题出在:攻击者可以构造畸形的 HAProxy 协议报文,让解码器在内存中不断累积未释放的数据,最终把 JVM 堆撑满。这是一个 high 级别的漏洞,意味着不需要认证、不需要特殊权限,只要能往你的 Netty 服务端口发 TCP 数据就能触发。

受影响的服务特征:

  • 使用了 HAProxyMessageHAProxyProtocolVersion 进行 PROXY 协议解析
  • ChannelPipeline 中加入了 HAProxyMessageDecoder
  • 服务端口对非信任网络可达(没有上游 L4 代理过滤)

如果你的 Netty 服务根本没引入 netty-codec-haproxy 依赖,这个 CVE 与你无关。但很多网关项目(如自研的 API Gateway、Service Mesh Sidecar)默认会开启 PROXY 协议支持,需要逐个项目排查。

CVE-2026-47691:DNS 解析器缓存可以被毒化

netty-resolver-dns 是 Netty 内置的异步 DNS 解析器,几乎所有用到 Netty HTTP 客户端或 gRPC 客户端的项目都会间接依赖它。漏洞允许攻击者通过伪造 DNS 响应注入恶意缓存记录,把你的出站请求导向攻击者控制的服务器。

这意味着:

  • 你的 Netty HTTP 客户端请求 https://internal-api.company.com,解析结果可能被替换成攻击者的 IP
  • gRPC 调用的目标地址可能被劫持
  • 任何基于域名的外部服务调用都存在中间人风险

这个漏洞的严重性在于 netty-resolver-dns 的使用面极广——即使你没有显式配置 DNS 解析,Netty 的 BootstrapHttpClient 默认就会走这个模块。

快速排查:你的项目是否受影响

第一步,确认依赖中是否包含这两个模块以及当前版本:

# 在项目根目录执行,排查 Netty 相关依赖的实际版本
mvn dependency:tree -Dincludes=io.netty:*

# 或者用 Gradle
gradle dependencies --configuration compileClasspath | grep netty

输出中重点关注这几行:

io.netty:netty-codec-haproxy:4.1.x   ← CVE-2026-48059
io.netty:netty-resolver-dns:4.1.x    ← CVE-2026-47691
io.netty:netty-all:4.1.x             ← 包含以上所有模块,两个 CVE 都受影响

第二步,确认你的服务是否在 Pipeline 中使用了 HAProxy 解码器:

# 在代码仓库中搜索
grep -rn "HAProxyMessageDecoder\|HAProxyMessage" --include="*.java" .

如果搜索结果为零,CVE-2026-48059 的直接风险可以降级。但 CVE-2026-47691 几乎无法绕开——只要你的 Netty 版本低于 4.2.15.Final 且有出站 DNS 解析行为,就存在暴露面。

升级与临时缓解

最彻底的方案是升级到 4.2.15.Final。Maven 项目修改 pom.xml

<properties>
    <netty.version>4.2.15.Final</netty.version>
</properties>

<!-- 如果用 netty-all 一把引入 -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>${netty.version}</version>
</dependency>

Gradle 项目:

dependencies {
    implementation "io.netty:netty-all:4.2.15.Final"
    // 或者按模块引入
    implementation "io.netty:netty-handler:4.2.15.Final"
    implementation "io.netty:netty-resolver-dns:4.2.15.Final"
}

升级后跑一遍集成测试,重点关注:

  • PROXY 协议解析是否正常(如果有用)
  • DNS 解析行为是否稳定(HTTP/gRPC 出站调用)
  • 连接池和 SSL/TLS 握手没有回归

如果暂时无法升级(比如正在做大版本迁移),可以采取临时缓解措施:

针对 HAProxy 内存耗尽——在 Pipeline 中对 HAProxy 解码器加长度限制:

// 临时缓解:限制 HAProxy 消息最大长度,防止内存无限膨胀
ChannelPipeline pipeline = ch.pipeline();
// maxHeaderLength 设为合理值(如 1024),超过直接断开连接
pipeline.addLast(new HAProxyMessageDecoder(maxHeaderLength));

针对 DNS 缓存中毒——切换到 JDK 内置解析器作为临时方案:

// 临时缓解:绕开 netty-resolver-dns,使用 JDK 默认解析器
import io.netty.resolver.DefaultAddressResolverGroup;

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
          .channel(NioSocketChannel.class)
          // 关键:替换默认的 DNS 解析器组
          .resolver(DefaultAddressResolverGroup.INSTANCE);

DefaultAddressResolverGroup.INSTANCE 调用的是 JDK 的 InetAddress.getAllByName,不走 Netty 的异步 DNS 缓存,虽然性能略有下降(同步解析),但规避了缓存中毒风险。等升级到 4.2.15.Final 后再切换回 RoundRobinDnsAddressResolverGroup

升级前的检查清单

检查项 说明
依赖树扫描 mvn dependency:tree 确认所有 netty 模块版本一致,避免部分模块漏升
HAProxy 解码器搜索 grep 代码仓库确认是否使用了 netty-codec-haproxy
出站 DNS 调用梳理 列出所有通过域名发起的 HTTP/gRPC 调用,这些是缓存中毒的攻击面
临时缓解是否生效 如果用了 DefaultAddressResolverGroup,确认 DNS 解析正常且无超时
回归测试 PROXY 协议、DNS 解析、TLS 握手、连接池四个维度必须覆盖
BOM 统一管理 如果项目用 Spring Boot 或其他 BOM 控制 Netty 版本,确认 BOM 也能更新到 4.2.15.Final

两个高危 CVE 都属于"低门槛、高后果"的类型——不需要认证、不需要复杂攻击链,只要网络可达就能尝试。升级本身风险不大(这是修复版本,没有 API 变更),拖延的风险反而更高。


相关推荐