Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-66752-HTTP-Request-Smuggling-via-Unparsed-Transfer-Encoding-Values-tiny_http- — Security Advisory: HTTP Request Smuggling via Unparsed Transfer-Encoding Values (tiny_http) | Kitploit
工具/GitHubGitHub/theopaid/cve-2026-66752-http-request-smuggling-via-unparsed-transfer-encoding-values-tiny_http-
Vulnerability AnalysisWeb Application ExploitationWeb SecurityPapers & Research
GitHubtheopaid/cve-2026-66752-http-request-smuggling-via-unparsed-transfer-encoding-values-tiny_http-

CVE-2026-66752-HTTP-Request-Smuggling-via-Unparsed-Transfer-Encoding-Values-tiny_http-

Security Advisory: HTTP Request Smuggling via Unparsed Transfer-Encoding Values (tiny_http)

查看仓库

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
22天前尚未审核

安全公告:通过未解析的 Transfer-Encoding 值实现 HTTP 请求走私(tiny_http)

分配的 CVE ID: CVE-2026-66752

摘要

tiny_http 只检查是否存在 Transfer-Encoding 请求头,从不检查其值。任何值(包括不是 chunked 的编码,以及最终元素不是 chunked 的编码列表)都会导致请求体被按 chunked 解码,同时 Content-Length 会被丢弃。

正确解析传输编码的前端会以与 tiny_http 不同的方式界定此类请求的边界。同一连接上两个参与者使用两种不同的边界界定方式,是请求走私的前提条件。发送带有非 chunked 编码的非 chunked 请求体,也会使 tiny_http 读取请求体失败,并且完全不返回任何响应。

受影响版本

仓库 URL:https://github.com/tiny-http/tiny-http

受影响所有已发布版本,直至并包括 0.12.0(2022-10-06),即当前版本
已验证0.6.2, 0.6.3, 0.8.0, 0.9.0, 0.10.0, 0.11.0, 0.12.0
修复版本撰写本文时尚无修复版本

严重性

CWE-444(HTTP 请求的解释不一致)。

CVSS 4.0 基础评分 6.3(中危) CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:L/SI:L/SA:N

威胁模型

远程、未认证的客户端发送原始 HTTP 请求。无需凭据或用户交互。

走私场景要求 tiny_http 位于正确转发 Transfer-Encoding 和 Content-Length 并正确应用 RFC 9112 第 6.1 节的前端或 CDN 之后,也就是说,该前端会将最终元素不是 chunked 的编码列表视为非 chunked,并回退到 Content-Length。这样一来,前端和 tiny_http 会对请求体结束的位置产生分歧。

无响应请求场景除了能够建立连接外,不需要任何其他条件。

根本原因

tiny_http-0.12.0/src/request.rs 第 143 至 153 行。该请求头被找到并克隆,但其值仅被检查是否存在:

root@kitploit:~
143      // finding the transfer-encoding header
144      let transfer_encoding = headers
145          .iter()
146          .find(|h: &&Header| h.field.equiv("Transfer-Encoding"))
147          .map(|h| h.value.clone());
148  
149      // finding the content-length header
150      let content_length = if transfer_encoding.is_some() {
151          // if transfer-encoding is specified, the Content-Length
152          // header must be ignored (RFC2616 #4.4)
153          None

tiny_http-0.12.0/src/request.rs 第 218 至 221 行随后无条件应用 chunked 解码器:

root@kitploit:~
218      } else if transfer_encoding.is_some() {
219          // if a transfer-encoding was specified, then "chunked" is ALWAYS applied
220          // over the message (RFC2616 #3.6)
221          Box::new(FusedReader::new(Decoder::new(source_data))) as Box<dyn Read + Send + 'static>

transfer_encoding 是一个保存原始值的 Option<AsciiString>,但没有任何代码检查其内容。RFC 9112 第 6.1 节要求请求的最终编码为 chunked,并要求服务器在否则的情况下拒绝该消息;第 6.3 节要求拒绝同时带有 Transfer-Encoding 和 Content-Length 的请求。

概念验证

步骤 1. 启动一个服务器,用于报告界定请求边界的请求头及其读取到的请求体。

root@kitploit:~
use std::io::Read;
use tiny_http::{Response, Server};

fn main() {
    let server = Server::http("127.0.0.1:8005").unwrap();
    for mut request in server.incoming_requests() {
        let te = request.headers().iter()
            .find(|h| h.field.equiv("Transfer-Encoding"))
            .map(|h| h.value.as_str().to_string());
        let cl = request.headers().iter()
            .find(|h| h.field.equiv("Content-Length"))
            .map(|h| h.value.as_str().to_string());
        let mut body = Vec::new();
        let r = request.as_reader().read_to_end(&mut body);
        println!("TE={:?} CL={:?} read={:?} body={:?}",
                 te, cl, r, String::from_utf8_lossy(&body));
        let _ = request.respond(Response::from_string("ok"));
    }
}

步骤 2. 发送一个带有 Transfer-Encoding: identity、匹配的 Content-Length 以及普通请求体的请求。任何前端都会将该请求体界定为 hello 这五个字节。

root@kitploit:~
printf 'POST / HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: identity\r\nContent-Length: 5\r\n\r\nhello' | nc -w 2 127.0.0.1 8005

结果:tiny_http 对一个并非 chunked 的请求体进行了 chunked 解码,将其丢弃,并且没有发送任何响应。客户端会一直等到自己的超时时间,连接被消耗。

root@kitploit:~
TE=Some("identity") CL=Some("5") read=Err(Custom { kind: InvalidInput, error: DecoderError }) body=""

步骤 3. 发送一个最终元素不是 chunked 的编码列表。

root@kitploit:~
printf 'POST / HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked, identity\r\n\r\n5\r\nhello\r\n0\r\n\r\n' | nc -w 2 127.0.0.1 8005

结果:tiny_http 接受该请求并按 chunked 解码,而 RFC 9112 第 6.1 节要求拒绝该请求:

root@kitploit:~
TE=Some("chunked, identity") CL=None read=Ok(5) body="hello"

作为对比,仅使用 Content-Length 以及正确的 Transfer-Encoding: chunked 都能正常处理,并得到 body="hello"。

影响

当 tiny_http 部署在正确解析传输编码的前端之后时,两个组件会对请求体结束的位置产生分歧。攻击者可以选择该分歧两侧的字节,这是将请求走私绕过前端路由和访问控制的标准设置。

与任何前端无关,步骤 2 和 3 展示了一个明显格式错误的请求,它会占用一个工作线程,并且根本收不到任何响应,因此客户端无法判断请求是否被拒绝。

修复措施

在 src/request.rs 第 144 行附近,按 Transfer-Encoding 的实际形式(逗号分隔的列表)对其进行解析:

对于带有请求体的请求,要求最终编码为 chunked,并对任何其他编码返回 400 拒绝,而不是按 chunked 解码。对于同时带有 Transfer-Encoding 和 Content-Length 的请求,应按照 RFC 9112 第 6.3 节对非代理服务器的要求予以拒绝,而不是在第 150 行静默忽略 Content-Length。

当请求体读取失败时,应返回 400,而不是丢弃请求且不发送任何响应。

下载工具