




















https://access.redhat.com/zh_CN/security/vulnerabilities/RHSB-2026-007
https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb
https://github.com/envoyproxy/envoy/security/advisories/GHSA-22m2-hvr2-xqc8
https://github.com/envoyproxy/envoy/security/advisories/GHSA-22m2-hvr2-xqc8
攻击者先往 HPACK 动态表植入一个大头部(如 4KB 的 Cookie) ↓ 然后在单个请求里塞几千个"单字节索引引用"(Index 62, Index 62, Index 62...) ↓ 服务器为每个引用重建/追加完整头部副本 → 内存 × 数千倍放大 ↓ 同时宣告 INITIAL_WINDOW_SIZE = 0(零窗口)→ 响应发不出去,流永远卡着 ↓ 已分配的内存放在那里不释放 → 10~20 秒内吃光 32GB RAM → OOM Kill / 拒绝服务
1.38 的官方修复
https://github.com/envoyproxy/envoy/pull/45518/changes
openssl 1.23的修复
https://github.com/envoyproxy/envoy-openssl/pull/553
https://github.com/envoyproxy/envoy-openssl/pull/562

有效的关键修复
https://github.com/envoyproxy/envoy-openssl/commit/3de6178c4353078e564d327061fe36c93dbd58c9
https://github.com/envoyproxy/envoy-openssl/commit/28e883a7490f856efab9645f39da9c58266aad7c
把解压的cookie分别计入 header 大小与header长度。
envoy.reloadable_features.http2_include_cookies_in_limits
在runtime_features.cc中设置,默认值为true。
header_list_size_too_large
cookies_total_bytes_too_large
envoy.reloadable_features.http2_max_cookies_size_in_kb 默认值为0.
max header byte
max header count
是HCM的两个配置项:
maxRequestHeadersKb 默认值 60KB
https://www.envoyproxy.io/docs/envoy/v1.32.13/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#extensions-filters-network-http-connection-manager-v3-httpconnectionmanager
maxReqestHeadersCount 默认值 100
https://www.envoyproxy.io/docs/envoy/v1.32.13/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-httpprotocoloptions


后续部分为AI生成,后进行的二次整理。
source/common/http/http2/codec_impl.h
Stream 新增 cookie_count_ 字段,记录拆分出的 cookie header 条数:
HeaderString cookies_; // 解压后拼接的 cookie 字符串(已有) uint32_t cookie_count_; // cookie header 条数(新增)
source/common/http/http2/codec_impl.cc — saveHeader()
HPACK 解压出的每个 header 进入 saveHeader()。如果是 cookie(被 reconstituteCrumbledCookies 识别并拼接到 cookies_),计数加一:
if (Utility::reconstituteCrumbledCookies(name, value, cookies_)) {
cookie_count_++; // cookie 条数 +1
} else {
headers().addViaMove(std::move(name), std::move(value));
}
source/common/http/http2/codec_impl.cc — saveHeader() 限制检查
原来的合并检查被拆分为三部分,每部分有独立的 error detail 和 counter:
|
检查项 |
触发条件 |
Error Detail |
|
header 总大小超限 |
|
|
|
header 总数超限 |
|
|
uint64_t headers_size = stream->headers().byteSize();
uint64_t headers_count = stream->headers().size();
// runtime guard 控制是否将 cookie 纳入计算(默认开启)
if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.http2_include_cookies_in_limits")) {
headers_size += stream->cookies_.size(); // cookie 字节数计入
headers_count += stream->cookie_count_; // cookie 条数计入
}
if (headers_size > max_headers_kb_ * 1024) {
stream->setDetails(Http2ResponseCodeDetails::get().header_list_size_too_large);
stats_.header_list_size_too_large_.inc();
return ERR_TEMPORAL_CALLBACK_FAILURE; // → RST_STREAM
}
if (headers_count > max_headers_count_) {
stream->setDetails(Http2ResponseCodeDetails::get().too_many_headers);
stats_.header_overflow_.inc();
return ERR_TEMPORAL_CALLBACK_FAILURE;
}
return 0;
source/common/http/http2/codec_stats.h — 新 counter:
COUNTER(header_list_size_too_large) // 总 header 大小超限(区别于 header_overflow) COUNTER(cookies_total_bytes_too_large) // cookie 重组大小超限
source/common/runtime/runtime_features.cc — Runtime guard:
RUNTIME_GUARD(envoy_reloadable_features_http2_include_cookies_in_limits);
新增独立的 http2_max_cookies_size_in_kb runtime guard,直接限制重组后 cookies 的总字节数,不依赖其他 header 累积的影响。
source/common/http/http2/codec_impl.h
ConnectionImpl 构造函数新增 runtime 参数和 max_cookie_size_bytes_ 成员:
ConnectionImpl(...
const uint32_t max_headers_kb, const uint32_t max_headers_count,
OptRef<Runtime::Loader> runtime = absl::nullopt); // 默认值保证向后兼容
const uint64_t max_cookie_size_bytes_{0}; // 0 = 不限制
ServerConnectionImpl 同样新增 runtime 参数并传递给父类:
ServerConnectionImpl(...,
Server::OverloadManager& overload_manager,
OptRef<Runtime::Loader> runtime = absl::nullopt);
source/common/http/http2/codec_impl.cc — 构造函数
从 runtime snapshot 读取配置值(KB → 字节):
max_cookie_size_bytes_(
runtime.has_value()
? runtime->snapshot().getInteger(
"envoy.reloadable_features.http2_max_cookies_size_in_kb", 0) * 1024
: 0)
source/common/http/http2/codec_impl.cc — saveHeader() 新增检查
在三层检查的最前面,独立判断 cookie 重组大小:
const uint64_t total_cookie_size = stream->cookies_.size();
if (max_cookie_size_bytes_ > 0 && total_cookie_size > max_cookie_size_bytes_) {
stream->setDetails(Http2ResponseCodeDetails::get().cookies_total_bytes_too_large);
stats_.cookies_total_bytes_too_large_.inc();
return ERR_TEMPORAL_CALLBACK_FAILURE;
}
调用链传递 runtime 参数:
conn_manager_utility.cc → autoCreateCodec() 新增 Runtime::Loader& 参数:
ServerConnectionPtr autoCreateCodec(..., Server::OverloadManager& overload_manager,
Runtime::Loader& runtime);
在创建 Http2::ServerConnectionImpl 时传入 runtime。
config.cc — HCM 创建 codec 时传递 runtime:
context_.serverFactoryContext().runtime()
admin.cc — Admin 接口创建 codec 时传递 runtime:
server_.runtime()
┌─────────────────────────────────────┐
│ HPACK 解压 header │
│ ↓ │
│ saveHeader() │
│ ↓ │
│ cookie? → cookies_ += value │
│ → cookie_count_++ │
│ other? → headers().add() │
│ ↓ │
│ ┌──── 三层检查 ────┐ │
│ │ │
│ │ 1. cookies_.size() │
│ │ > max_cookie_size_bytes_? │
│ │ → cookies_total_bytes_too_large │
│ │ │
│ │ 2. (headers + cookies).byteSize │
│ │ > max_headers_kb * 1024? │
│ │ → header_list_size_too_large │
│ │ │
│ │ 3. (headers + cookies).count │
│ │ > max_headers_count? │
│ │ → too_many_headers │
│ │ │
│ └───────────────────────────────────────┘
│ ↓
│ ERR_TEMPORAL_CALLBACK_FAILURE
│ ↓
│ RST_STREAM
└─────────────────────────────────────┘
|
防御层 |
来源 |
Runtime Guard |
|
Cookie 独立大小限制 |
|
|
|
Cookie 参与 header 总大小限制 |
|
|
|
Cookie 参与 header 总数量限制 |
|
|
默认值安全:两个 guard 默认均启用保护,http2_max_cookies_size_in_kb 默认 0(无单独限制,依赖总大小限制生效)
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。