theopaid/CVE-2026-67183-Unauthenticated-Memory-Leak-Leads-To-Memory-Exhaustion-TinyWeb-

GitHub: theopaid/CVE-2026-67183-Unauthenticated-Memory-Leak-Leads-To-Memory-Exhaustion-TinyWeb-

该仓库披露了 TinyWeb HTTP 服务器因请求对象缺少析构函数而导致的未授权内存耗尽漏洞(CVE-2026-67183),包含完整的技术分析、PoC 和修复建议。

Stars: 0 | Forks: 0

# 安全公告:未授权内存泄漏导致内存耗尽 (TinyWeb) **分配的 CVE ID:** CVE-2026-67183 ## 摘要 TinyWeb 在解析每个请求时会分配多个对象,且从不释放它们。请求和 header 结构没有析构函数,在发送响应后也没有任何代码删除它们。Worker 的内存随着每个请求不断增长且从不下降,因此稳定的普通请求流会导致 Worker 内存耗尽。 ## 受影响软件 - 项目:TinyWeb (https://github.com/GeneralSandman/TinyWeb) - 构建报告的版本:`TnyWeb/0.0.8` - 受影响的提交:`e48f15d` (2018-11-20),即引入这些结构和解析器的提交,到 `a381da2` (2023-11-22,`master` 分支上的最新提交)。 - 修复版本:无。 ## 分类 - CWE-401:有效生命周期结束后未释放内存 - CVSS 4.0 基础分数:8.7 (高) - 向量:`CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N` ## 威胁模型 未经身份验证的远程攻击者能够访问服务器的监听 TCP 端口(在默认配置中为 9090)并以适中的持续速率发送请求。不需要任何凭证或用户交互。请求可以是格式良好的;不需要特殊的 payload。 ## 技术细节 对于每个请求,`HttpParser::execute()` 都会分配一个 `Url`、一个 `HttpHeaders` 以及每个 header 行对应的一个 `HttpHeader`: ``` // src/tiny_http/http_parser.cc:1692 request->url = new Url; // src/tiny_http/http_parser.cc:1709 request->headers = new HttpHeaders; // src/tiny_http/http_parser.cc:1033-1040 HttpHeader* header = new HttpHeader; return_val = parseHeader(stream, offset, len, header); ... result->generals.push_back(header); // stored in a raw-pointer list ``` `HttpRequest` 和 `HttpHeaders` 是没有析构函数的普通结构体,因此销毁 `HttpRequest` 时不会释放其中任何内容: ``` // src/tiny_http/http_parser.h:442 typedef struct HttpRequest { ... Url* url; HttpHeaders* headers; HttpBody* body; } HttpRequest; // src/tiny_http/http_parser.h:279-304 typedef struct HttpHeaders { ... std::list generals; // raw pointers, never deleted ... } HttpHeaders; ``` `WebProtocol` 使用 `std::shared_ptr` 来持有请求 (`src/tiny_http/http_protocol.h:49`)。当下一个请求替换它时,默认的 `~HttpRequest` 会运行,并泄漏 `url`、`headers`、`body` 以及 `generals` 中的每个 `HttpHeader`。代码中唯一的 `delete request` 位于 `getDataFromProxy()` (`src/tiny_http/http_protocol.cc:194`) 中,但请求路径从未调用过该函数。来自内存池的每请求响应缓冲区进一步加剧了内存的增长。 ## 概念验证 1. 使用默认配置启动服务器(监听 9090 端口)。记录某个 worker 的进程 ID。 2. 记录该 worker 的常驻内存: ``` grep VmRSS /proc//status ``` 3. 发送一批普通请求: ``` for i in $(seq 1 2000); do curl -s -o /dev/null http://TARGET:9090/ done ``` 4. 再次读取 `VmRSS`。它已经增长并且之后不会下降。一次典型的运行结果: ``` VmRSS before: 3704 kB after 500 requests: 4788 kB after 1000 requests: 22068 kB after 1500 requests: 41652 kB after 2000 requests: 59956 kB ``` 这种增长是单调的,每个请求大约增长 20 到 28 kB,没有停滞期。重复发送该批次会继续增加内存,直到 Worker 因内存耗尽而被杀掉。 ## 影响 未经身份验证的攻击者可以通过持续的请求流耗尽 Worker 的内存,并迫使系统出现内存不足的情况,从而导致拒绝服务。随着时间的推移,普通流量也会发生泄漏,因此即使没有攻击者,这种情况也可能发生。 ## 修复建议 为 `HttpRequest` 和 `HttpHeaders` 提供析构函数,以释放 `url`、`headers`、`body` 以及 `generals` 中的每个 `HttpHeader`,或者使用智能指针来持有它们以便自动释放。此外,一旦响应发送完毕,也应释放每个请求对应的内存池缓冲区。
标签:C++, CVE, Web服务器, 内存泄漏, 拒绝服务, 数字签名, 数据擦除, 漏洞分析, 路径探测, 配置错误