Skip to main content
bin9chn@blog:~/posts/学习笔记

HTTP/2 Bomb:压缩放大与流控停滞为什么会叠加

从 HPACK 动态表与 HTTP/2 流控出发,理解“一个字节放大成一次分配”之后再被长期占用的资源路径。

2 min read
HTTP/2 Bomb:压缩放大与流控停滞为什么会叠加 封面

HTTP/2 Bomb 的研究价值不在单个 payload,而在两个长期存在的机制被放到同一条资源生命周期里观察:一边放大内存分配,一边阻止这些内存被及时释放。

HPACK 的放大面

HPACK 是 HTTP/2 的有状态头部压缩方案。发送端可以把头部写入动态表,之后使用短索引反复引用同一条内容。对发送端来说,索引可能只是一个字节;对接收端来说,每次引用都需要物化一份新的头部实例。

传统防护通常关注解码后的头部字符串有多大。但实现还会为每个字段维护结构体、指针、缓冲区和其他簿记信息。即使头部内容接近空,字段数量本身也可能产生显著放大。

Cookie 是研究中的一个典型入口。RFC 9113 允许把 Cookie 拆成多个字段发送,如果服务端只限制解码后的总大小,却没有把每个 Cookie 分片计入字段数量,就会留下数量型放大空间。

流控的停留面

HTTP/2 在流级别提供流量控制。客户端控制服务端响应的发送窗口。把窗口设为零后,服务端响应无法完成;再用短小的 WINDOW_UPDATE 维持连接状态,已经分配的资源就可能继续驻留在内存中。

单独看,压缩放大只是比例问题;单独看,慢速连接也只是连接管理问题。组合之后,攻击者可以在较低带宽下持续把服务器内存维持在压力区间。

防御需要两个维度

一个健壮的 HTTP/2 入口至少需要同时考虑:

  1. 单请求的头部字段数量,包括 Cookie 分片。
  2. 解码后的头部总大小。
  3. 停滞流的生存时间,即使客户端仍在发送流控更新。
  4. 连接级与进程级的内存上限。

nginx 后续引入 max_headers,Apache httpd 的 mod_http2 修复则让 Cookie 分片计入 LimitRequestFields。这说明修复点不在某个字符串解析器,而在协议资源的计量方式。

研究启示

安全审计容易在一个函数里寻找越界或注入,但资源耗尽往往发生在多个组件的契约之间。问“这个限制覆盖了什么”之外,还要问“限制没有覆盖的对象何时释放”。

查看 HTTP/2 Bomb 研究仓库

相关文章

全部文章 →