Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

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

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

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
Brotli-Node.js-CVE-2026-111497-Broccoli2Shell-Node2Shell-HTTP2Shell- — 针对 CVE-2026-111497 的公告与分析:该漏洞是可通过 Node.js HTTP 解压缩触发的 Brotli 解码器越界写入,内容涵盖根本原因、补丁差异、检测规则和缓解措施。 | Kitploit
工具/GitHubGitHub/certbn/brotli-node.js-cve-2026-111497-broccoli2shell-node2shell-http2shell-
内存取证漏洞分析漏洞利用Web安全威胁情报事件响应
GitHubcertbn/brotli-node.js-cve-2026-111497-broccoli2shell-node2shell-http2shell-

Brotli-Node.js-CVE-2026-111497-Broccoli2Shell-Node2Shell-HTTP2Shell-

针对 CVE-2026-111497 的公告与分析:该漏洞是可通过 Node.js HTTP 解压缩触发的 Brotli 解码器越界写入,内容涵盖根本原因、补丁差异、检测规则和缓解措施。

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库
12天前尚未审核

CVE-2026-111497:Google Brotli 解码器 Block-Switch 返回值未检查导致越界写入(Node2Shell / HTTP2Shell / Broccoli2Shell)

CVSS CVSS Type KEV

最后确认日期:2026-11-04 (KST)。各项数值仅记录了下文 References 来源中确认的值,若来源之间数值不同,则全部并列标注。

📌 TL;DR

  • 是什么:Google Brotli C 解码器(c/dec/decode.c)忽略了错误块切换(block switch)的错误返回值,在损坏状态下继续解码,导致在缓冲区边界外写入(越界写入)。
  • 在哪里:包含 Brotli 1.0.3 ~ 1.2.0 的所有软件——Node.js(22/24/26 及 EOL 版本)、Python Brotli/brotlicffi、Bun、.NET、Envoy、Istio 等。必须存在攻击者控制的 Content-Encoding: br 数据的解压路径才会受到影响。
  • 有多危险:无需认证即可远程实现 DoS、内存泄露、RCE(CNA CVSS 4.0 9.2),已于 2026-10-27 列入 CISA KEV。需要立即修补。

📋 基本信息

项目内容
CVE IDCVE-2026-111497 (GHSA-9v8h-qqgm-4m35)
别名Node2Shell(Imperva 命名)、HTTP2Shell、Broccoli2Shell。与名称不同,并非 HTTP/2 协议缺陷
公开日期2026-10-21 Node.js 安全发布及 Brotli 补丁发布 / 2026-10-22 CVE 记录公开
发现者OpenAI Codex Security (Khai Tran, Sylvie Mayer)
影响产品/版本Google Brotli(libbrotlidec) 1.0.3 ~ 1.2.0 以及捆绑/链接该库的产品(见下表)
补丁版本Brotli 1.0.10 / 1.1.1 / 1.2.1、Node.js 22.23.4 / 24.22.1 / 26.12.1、Python Brotli 1.2.1、brotlicffi 1.2.1.0、Bun 1.4.4
CVSS v4.0 (CNA: Google)9.2 Critical — CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
CVSS v3.1 (NVD)9.8 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVSS v3.1 (Red Hat / Amazon Linux)8.1 — CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H(反映攻击要求 AT:P 及平台加固)
厂商自身评级Node.js: High / Red Hat: Important
CWECWE-787 越界写入(NVD、Red Hat、加拿大网络中心) / CWE-252 未检查返回值(CISA KEV 描述,部分分析文章作为根本原因并列标注)
实际利用情况已确认利用。 CISA KEV 于 2026-10-27 列入,联邦机构行动截止日期 2026-11-10。蜜罐运营商(Previdian、ELLIO)于 10-26~27 观测到利用尝试

影响范围详情

组件影响版本修复版本
Google Brotli (C, libbrotlidec)1.0.3 ~ 1.2.01.0.10, 1.1.1, 1.2.1
Node.js 26.x (Current)低于 26.12.126.12.1
Node.js 24.x (LTS)低于 24.22.124.22.1
Node.js 22.x (LTS)低于 22.23.422.23.4
Node.js 25.x / 23.x / 20.x 及以下所有版本 (EOL)无补丁 → 迁移至 22/24/26
Bun1.4.3 及以下1.4.4
Python Brotli (PyPI)1.2.0 及以下1.2.1
Python brotlicffi低于 1.2.1.01.2.1.0
.NET / PowerShell参考厂商建议Microsoft 紧急 .NET 更新 (dotnet/announcements#494)
Envoy / Istio参考厂商建议10 月初发布修复版本(未明确说明缺陷)
VMware SDDC Manager (VCF / vSphere Foundation)参考 Broadcom 建议参考 Broadcom 建议

间接暴露路径:Python requests、urllib3、aiohttp[speedups]、httpx 在安装了 Brotli/brotlicffi 时会自动解压 br 响应。curl 在使用解压选项时也会受影响。

主要日期 (2026)

日期事件
02-27向 google/brotli 仓库提交修复提交(标记为安全议题,未发布)
10月初发布 Envoy / Istio 修复版本
10-21Node.js 安全版本发布(22.23.4 / 24.22.1 / 26.12.1),Google Brotli 1.0.10 / 1.1.1 / 1.2.1 发布
10-22CVE 记录公开,Imperva 在 Node.js 24.22.0(Linux arm64)上演示了代码执行
10-23发布已修补的 PyPI 包
10-25Microsoft .NET 公告及更新
10-26ELLIO 报告利用流量
10-27列入 CISA KEV(处置期限 11-10)

⚠️ 在10月24日至28日之间撰写的一些分析文章称“未确认实际攻击、未列入 KEV”,但这是以 KEV 列入之前的时点为准,与当前情况不同。

🔍 漏洞根因分析(Root Cause)

1. 是什么:被重载的 BROTLI_FALSE 返回值

Brotli 解码是一个状态机(state machine)。流由元块(metablock)单元构成,在每个元块内部会出现用于切换字面量(literal)、插入-复制命令(insert-and-copy command)和距离(distance)的**块类型(block switch)**的指令。

DecodeBlockTypeAndLength() 解析块切换并返回 BROTLI_BOOL。问题在于 BROTLI_FALSE 被用于两种完全不同的含义。

含义性质正确处理
需要更多输入(needs more input)可恢复等待下一次输入后恢复
元块中只有1个块类型,切换本身不可能致命格式错误拒绝该流

2. 为什么:返回值被忽略(CWE-252)

调用方未检查该返回值。

  • 命令流的块切换包装函数(DecodeCommandBlockSwitch)被声明为 static void,不保留返回值,BROTLI_SAFE 宏的 non-safe 分支也只是调用函数并丢弃结果。(SonicWall 分析)
  • 另一项分析(Redfox)说明,在字面量块切换路径(DecodeLiteralBlockSwitch)中返回值被完全丢弃。各分析所指出的函数不同,但根据发行版补丁说明(TuxCare),字面量、命令、距离三种块切换解码器全部都被修改为返回错误码,因此可以认为三条路径均相关。

结果,即使发生格式错误,解码器也会像切换成功一样继续推进,块长度计数器保持为0,位置(position)·距离状态被带入本应被拒绝的路径。

3. 如何:损坏的状态导致 OOB Write(CWE-787)

  • 解码器因等待输入而暂停(parked)期间,发生越过所保留的 8字节内部输入缓冲区 的写入,覆盖相邻解码器状态(BrotliDecoderState)的位置·距离字段。
  • 随后 ProcessCommandsInternal() 的反向引用复制(backward-reference copy)以 copy_dst = &s->ringbuffer[pos] 计算目标,并通过 memmove16 执行 16字节向量存储。由于 pos 不再被限制在环形缓冲区范围内,写入发生在分配区域之外。
  • 攻击者可以操纵 pos,因此这成为 write-what-where 原语(primitive)。

4. 补丁对比(Before / After)

以下是根据公开分析(SonicWall、Redfox、TuxCare 补丁说明)的叙述重构变更要点的概念代码。并非实际提交的原文代码,条件表达式等细节为推测。准确的 diff 请从 google/brotli v1.2.1 发布及 Node.js deps/brotli 变更部分确认。(本文档撰写时未能将修复提交哈希作为一手来源确认。)

Before(脆弱)

/* 형식 오류와 "입력 부족"이 같은 BROTLI_FALSE로 표현됨 */
static BROTLI_BOOL DecodeBlockTypeAndLength(int safe, BrotliDecoderState* s, int tree_type) {
  ...
  if (/* 블록 타입이 1개뿐인 메타블록 */) {
    return BROTLI_FALSE;          /* 치명적 오류지만 복구 가능 신호와 구분 불가 */
  }
  ...
  return BROTLI_TRUE;
}

static void DecodeCommandBlockSwitch(BrotliDecoderState* s) {
  DecodeBlockTypeAndLength(0, s, 1);   /* 반환값 폐기 → 손상 상태로 계속 진행 */
}

之后(补丁)

/* 명시적 오류 코드 반환 */
static BrotliDecoderErrorCode DecodeBlockTypeAndLength(int safe, BrotliDecoderState* s, int tree_type) {
  ...
  if (/* 블록 타입이 1개뿐인 메타블록 */) {
    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH);   /* 신규 오류 코드 */
  }
  ...
  return BROTLI_DECODER_SUCCESS;
}

/* 리터럴/명령/거리 블록 전환 래퍼가 오류 코드를 전파하고,
   ProcessCommandsInternal()은 신규 매크로 BROTLI_SAFE_WITH_STATUS로
   결과를 확인해 비성공 시 디코딩을 즉시 중단 */
分类BeforeAfter
返回类型BROTLI_BOOL(语义重叠)BrotliDecoderErrorCode(语义明确)
错误块切换BROTLI_FALSE → 忽略返回 BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH
调用方void 包装器,丢弃结果错误传播 + 通过 BROTLI_SAFE_WITH_STATUS 检查后中止
结果以损坏状态继续解码 → OOB Write正常拒绝该流

修补后的 Node.js 会以 ERR__ERROR_FORMAT_BLOCK_SWITCH 错误拒绝此流。新常量在 Node.js 中通过 zlib.constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH 暴露,在修复构建中为 -17,在易受攻击的构建中为 undefined(Redfox)。

⚔️ 攻击场景

攻击前提条件

条件内容
认证不需要 — 解压缩在应用程序认证逻辑之前执行
网络位置远程(AV:N)。目标必须具有解压攻击者控制的 Brotli 数据的路径
易受攻击版本包含 Brotli 1.0.3 ~ 1.2.0 的运行时/库
流条件块类型为 1 个的元块 + 错误的块切换
传递方式需要分块(chunked)传递以使解码器因等待输入而暂停。一次性(one-shot)解码会一次性解压全部内容,无法分离损坏阶段
载荷大小为耗尽块长度计数器,至少需要约 2MB,按实际编码计算需要约 22~23MB 级别的流(SonicWall,公开 PoC 实验室)

暴露判定标准:纯 Node.js http 服务器即使接收到 br 正文也不会自动解压。必须由代码或中间件调用解码器。主要暴露路径如下。

方向路径备注
入站Express 5 / body-parser 2.x 的 json()、raw() 等默认 inflate 设置Imperva 在 Express 5.0.05.3.0 / body-parser 2.0.12.3.0 中确认。Express 4 会拒绝 br 正文
出站Node.js 内置 fetch()、Python requests/urllib3/aiohttp/httpxWebhook、链接预览、URL 抓取功能等。WAF 无法看到的路径
直接调用zlib.brotliDecompress*、createBrotliDecompress、brotli.decompress 等用于不可信输入的情况

分步流程(概念层面)

路径 A — 入站请求正文

sequenceDiagram
    autonumber
    participant A as 공격자
    participant P as 리버스 프록시/WAF
    participant N as Node.js 앱 (Express 5)
    participant D as Brotli 디코더 (취약)

    A->>P: POST /endpoint<br/>Content-Encoding: br<br/>Transfer-Encoding: chunked
    P->>N: 요청 전달 (본문 크기 제한 없을 때)
    N->>D: body-parser가 인증 전 자동 inflate
    Note over D: 1단계: 대용량 스트림으로 블록 길이 카운터 소진<br/>잘못된 블록 전환 → BROTLI_FALSE 무시
    Note over D: 디코더가 손상 상태로 입력 대기(parked)
    A->>N: 2단계: 작은 청크 추가 전송
    N->>D: 이어서 디코딩
    Note over D: 8바이트 버퍼 초과 쓰기 → pos/distance 위조<br/>memmove16이 ringbuffer+pos에 16바이트 저장
    D-->>N: 메모리 손상 → 크래시 또는 코드 실행

路径 B — 出站响应(类 SSRF 模式)

sequenceDiagram
    autonumber
    participant A as 공격자
    participant N as 대상 서비스 (fetch / requests)
    participant S as 공격자 제어 서버
    participant D as Brotli 디코더 (취약)

    A->>N: "이 URL 미리보기 / 웹훅 등록" 요청
    N->>S: GET (Accept-Encoding에 br 포함)
    S-->>N: Content-Encoding: br 조작된 응답
    N->>D: HTTP 클라이언트가 자동 해제
    D-->>N: 메모리 손상 → 크래시 또는 코드 실행
    Note over N,S: 아웃바운드 응답은 인바운드 WAF를 거치지 않음

预期影响

下载工具