EaEa0001/servu-cve-2026-28318-poc

GitHub: EaEa0001/servu-cve-2026-28318-poc

针对 SolarWinds Serv-U 预认证堆损坏崩溃漏洞(CVE-2026-28318)的防御性安全研究项目,提供根因分析与仅限 DoS 的 PoC。

Stars: 1 | Forks: 0

# CVE-2026-28318 — SolarWinds Serv-U "Content-Encoding: deflate" 预认证崩溃 ## ⚠️ 免责声明 / 范围 - 这是针对**已修补且已公开披露**漏洞的**防御性安全研究** (修复程序已于 **2026-06-04** 在 Serv-U 15.5.4 Hotfix 1 中发布;并被列入 **CISA KEV**)。 - 此处的 PoC 仅会导致您**拥有或获得明确授权测试**的 Serv-U 实例**崩溃**。 它是**仅限 DoS** 的 — 不包含或演示任何远程代码执行(参见*严重性*)。 - 使用它来**验证您自己系统上的补丁状态和检测**。不要将其指向您无法控制的系统。 您需自行负责遵守适用的法律。 ## 受影响 / 已修复 | | | |---|---| | 产品 | SolarWinds Serv-U (FTP / MFT / 文件服务器) | | 受影响版本 | 该分支中的 15.5.4 及更早版本(**未包含** Hotfix 1,分析基于内部版本 **15.5.4.108**) | | 已修复版本 | **Serv-U 15.5.4 Hotfix 1**(发布于 2026-06-04) | | 向量 | 未认证、网络(HTTP/HTTPS 管理/Web 端口) | | 公开类别 | CWE-400 不受控的资源消耗 · DoS · CVSS 7.5 · CISA KEV | | 实际类别 | **CWE-763 释放无效指针 / CWE-590 释放非堆内存** → 堆损坏 | ## 摘要 (TL;DR) 任何携带 `Content-Encoding: deflate` **且具有有效 deflate 主体**的 HTTP 请求都会导致服务崩溃。 处理程序会解压缩该主体,然后**释放指向*已压缩*主体的指针**并替换为解压缩后的缓冲区 — 但该指针是一个**位于 HTTP 接收缓冲区内部的指针**(它指向紧随 `\r\n\r\n` 之后的主体),**而不是堆分配基址**。 在非基址且未对齐的指针上调用 `free()` 会损坏堆,导致进程终止。 由于该漏洞出在*主体指针如何被释放* — 而不在于*生成了多少*数据 — 因此即使是解压后仅有几 KB 的约 25 字节压缩主体也能稳定触发崩溃。内存使用量不会增加;这并不是一个“zip/deflate 炸弹”。 ## 根本原因 deflate 解码例程位于 `RhinoNET.dll`(Serv-U 的网络库)中,并在 HTTP 接收路径 (`ProcessReceive`) 中,当头部解析器看到 `Content-Encoding: deflate` 并设置了“deflate”标志后被触发。 简而言之,该例程的调用方式为 `decode(this, &bodyPtr, &bodyLen)`,其执行过程如下: ``` 1. inflate bodyPtr[0..bodyLen] -> grows an accumulator buffer `acc` (stock zlib, bounded, correct) 2. free(*bodyPtr) <-- *bodyPtr is an INTERIOR pointer into the receive buffer 3. *bodyPtr = acc // replace compressed body with decompressed buffer 4. *bodyLen = total ``` 第 2 步是问题所在。`*bodyPtr` 并不是一个独立分配的内存块:它指向**单个 HTTP 接收缓冲区内部**的请求主体,即 `receive_buffer + header_length`。释放一个内部(且 16 字节未对齐的)指针会导致分配器将受攻击者影响的区域解析为堆块头部 → 堆元数据损坏 → `0xC0000374`。 ### 排除了哪些情况(以免您走弯路) 以下两个“显而易见”的假设都是**错误**的,并已在运行时验证: - **不是 inflate/解压溢出。** 解压器是标准的 `zlib1.dll!inflate`,并在每次调用时严格遵守 `avail_out`(在 100 多个数据块中观察到;零越界写入)。 - **不是累加器溢出。** 不断增长的输出缓冲区每轮分配的大小为 `prev_total + produced + 1` 并准确地写入相同大小 —— 非常紧凑,没有溢出。 损坏完全是由于第 2 步中无效的 `free()` 造成的。 ## 证据 在发送解压后为 `"A" * 8192` 的 `Content-Encoding: deflate` 请求时,针对 Serv-U 15.5.4.108 在运行时(通过 Frida)捕获: - **被释放的指针是 `…ce` — `mod 16 == 14`。** 堆分配基址是 16 字节对齐的,因此这不是分配基址;它是一个内部指针。 - **被释放指针*之前*的 48 字节是 HTTP 头部尾部**,以 `\r\n\r\n` 结尾: …tream\r\nContent-Length: 26\r\nConnection: close\r\n\r\n - **被释放指针*处*的字节是原始 deflate 流**(`ed c1 01 0d 00 …`)。 - **崩溃签名:** 错误模块为 `ntdll.dll`,异常 `0xC0000374` (`STATUS_HEAP_CORRUPTION`),调用源自 `RhinoNET.dll` deflate 处理程序中的 `free`。崩溃前最后一次堆操作正是此 `free(bodyPtr)`。 - **与大小无关:** 解压后仅约 4 KB(压缩后约几十字节)的主体同样会崩溃;工作集内存不会增加。 ## 严重性 - **已确认:** 导致 Serv-U 服务(DoS)的**未认证远程崩溃**。服务可能会自动重启,但持续的请求会使其保持宕机状态,并可能耗尽 Windows 服务恢复机制。 - **超出 DoS — 未经证实。** 被释放的“块头部”与**受攻击者控制的 HTTP 头部字节**重叠,原则上这比单纯的 DoS 是更强的利用原语。然而,在现代 Windows(Segment Heap)上,无效的 `free` 在我们的测试中会**快速失败**(`0xC0000374`),并且**我们未能实现代码执行。** 请将其视为*具有内存安全根本原因的预认证堆损坏 DoS*;不要假设会发生 RCE。 ## 复现 需要 Python 3(仅限标准库)。将其指向您已获授权测试的 Serv-U HTTP 监听器。在 Windows 上,它使用一次 `Get-NetTCPConnection` 调用来读取监听器 PID,并使用应用程序事件日志来确认堆损坏崩溃。 ``` python poc_verify.py # default 127.0.0.1:80, tiny packet, 1 shot python poc_verify.py --host --port 80 python poc_verify.py --big # body decompresses to 8192 bytes python poc_verify.py --shots 3 python poc_verify.py --no-events # skip event-log check (no privileges needed) ``` 该 PoC 构建了一个最小请求: ``` POST / HTTP/1.1 Host: Content-Encoding: deflate Content-Type: application/octet-stream Content-Length: Connection: close ``` 如果服务崩溃(监听器 PID 发生变化 / 出现 `0xC0000374` 事件),它会报告 **PASS**;如果服务存活(已修补、未受影响或主体未被作为 deflate 处理),则报告 **FAIL**。 ## 缓解措施 1. **应用 Serv-U 15.5.4 Hotfix 1**(或更高版本)。 2. **临时方案:** 在 Serv-U 前端,剥离或拒绝 HTTP/HTTPS 监听器上的入站 `Content-Encoding`,例如在反向代理上: if ($http_content_encoding) { return 400; } 3. 限制 Serv-U Web/管理端口的网络暴露。 ## 方法论(分析方式) - 静态分析:对 `RhinoNET.dll` / `Serv-U.exe` 进行参数化 PE 反汇编(镜像基址 `0x180000000`),以映射 接收 → 头部解析 → deflate 解码 的路径,并定位错误的 `free`。 - 动态分析:对实时服务进行 Frida 插桩 — 挂钩解压器以证明 `zlib` 遵守 `avail_out`,将解码调用的每个 `alloc`/`free`/`memcpy` 追踪到磁盘,并使用进程异常处理程序在损坏发生的瞬间捕获错误指令和 `0xC0000374` 堆栈。随后通过转储被释放指针周围的字节(HTTP 头部尾部 + 原始 deflate 主体,16 字节未对齐)确认了内部指针的释放。 分析中引用的偏移量特定于内部版本 15.5.4.108,且在不同版本中会有所不同。 ## 参考资料 - SolarWinds — Serv-U 15.5.4 Hotfix 1 发行说明 - NVD — CVE-2026-28318 - CISA KEV 目录 — CVE-2026-28318 *作为防御性研究,在供应商补丁可用后发布。PoC 仅限 DoS 用途,旨在用于授权测试。*
标签:Maven, PoC, 拒绝服务攻击, 暴力破解, 漏洞分析, 漏洞验证, 路径探测, 逆向工具, 配置错误