文章总结: hpack库存在CVE-2026-59980中危漏洞,其变长整数解码无上限导致恶意载荷可造成解析耗时平方级放大,形成连接级拒绝服务。4.2.0版本通过限制整数范围修复。建议升级依赖并在代理层限制连接参数,同时建立告警与复测清单。 综合评分: 85 文章分类: 漏洞分析,应急响应,安全工具,解决方案
hpack:一个畸形头部块,如何拖垮 HTTP/2 解析线程
原创
云梦DC 云梦DC
云梦安全
2026年10月2日 09:00 河南
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
2026 年 9 月 24 日,hpack 披露 GHSA-8v8h-hg4w-mvq2(CVE-2026-59980,中危)。hpack 是 Python 里的 HPACK 实现——HTTP/2 的头部压缩格式(RFC 7541)。它不在你的业务代码里,而在 gunicorn、hypercorn、各类 ASGI/WSGI 服务器和 HTTP/2 客户端的依赖树里。所以这个漏洞的形态不是“数据被读走”,而是“解析线程被占满”。
这个问题的看点不在载荷多精巧,而在“异常抛出来了,但代价已经付完了”。
变长整数字段没有上限,代价是平方级放大
HPACK 里的长度、索引这类整数用变长编码表示:7 位有效位加一个续位标记。解码器按 RFC 7541 的语义一路读续字节,直到遇到最高位为 0 的字节为止。规范并没有规定“最多允许多少个续字节”,所以上限必须由解码器实现自己给出。
演示脚本构造的载荷很朴素:一个 literal-header-without-index 前缀,加一个被撑爆的 name length 字段,后面跟着成百上千个 0xff。在 hpack 4.1.0 上,同一份载荷从 1KB 涨到 195KB(放大 199 倍),解析耗时从 0.001 秒涨到 7.371 秒,放大 9930 倍。中间几档同样明显:31KB 是 0.193 秒,125KB 已经到 2.678 秒。载荷线性增长、耗时平方级放大,这是典型的“边读边重复处理”的实现特征。
作为对照,脚本还构造了一份约 107KB 的合法头部块(140 个字段),线性解析只要 0.059 秒,140 个字段全部正常解出。慢的不是“头部块大”,而是“这个字段畸形”。
有报错,不等于有防护
请注意上图中“结果”那一列:每一档都抛出了 HPACKDecodingError: Truncated header block。异常确实被抛了出来,但 7.371 秒的计算已经花掉了。
这是本次复现最值得记住的一点:校验发生在“字段长度越界”这个判断上,而解码器在做出判断之前,已经按变长整数语义把连续字节读成了一个大整数——成本先发生,异常后到达。把“有异常”当成“有防护”,会漏掉这类先耗资源、再报错的问题。
4.2.0 的修复:把上限提前
升级到 4.2.0 后,同一份载荷全部在 0.000–0.002 秒内被拒绝,异常文案也变了:Variable integer representation is too long。文案变化本身就是修复位置的证据——变长整数被限制在 uint32 范围内,畸形载荷在进入大数运算之前就被否定,耗时不再随载荷增长。对照组里 140 个字段的合法头部块解析耗时 0.055 秒,功能没有受影响。
为什么“一个连接”会拖累“很多请求”
HTTP/2 的特性是连接复用:一个连接上承载成百上千个流,头部解析是这条连接上的共享环节。当解析线程被一个畸形头部块占住,受影响的不是那一个请求,而是同一进程里其它连接与请求的排队时间。放在公网上,这是成本极低的连接级拒绝服务——攻击者只需要很小的带宽。
因此防护要分两层。依赖层:尽快升级 hpack 以及所有依赖它的服务器与客户端。部署层:不要假设上游一定处理得当,在反向代理或负载均衡上限制单个连接的头部块大小、单连接并发流数以及按来源的连接建立速率;对暴露在公网的 HTTP/2 服务建立连接数基线与异常断连告警。
复测清单
升级后用同一个脚本跑对照,确认三件事:畸形载荷的耗时回到毫秒级;异常文案是 Variable integer representation is too long;合法的、字段数很多的头部块仍然能被正常解析。第三条最容易被跳过,但它决定了这次升级会不会把正常业务一起挡在门外。
谁在依赖 hpack
这个漏洞不写在你的业务代码里,但它可能出现在任何解析 HTTP/2 头部的地方。自查的第一步是看依赖树:Python 环境里用 pip list 配合 pip show hpack,或在容器镜像里直接查 site-packages/hpack 的版本;第二步是找出谁在用它——gunicorn、hypercorn、httpx、各类 ASGI 网关都会引入它,浏览器自动化、抓取框架和内部代理同样可能带着它;第三步是确认这些服务里,哪些真的在对外提供 HTTP/2。
一个容易被忽略的点是“被动依赖”:服务本身只监听 HTTP/1.1,但某个上游或内部调用链上跑着 hpack 旧版本,攻击面依然存在,只是入口换了位置。因此升级时建议按镜像和依赖锁文件统一推,而不是逐个包手动改——这类底层库的版本漂移,往往就是下一个复现的起点。
一句话总结
协议解析器的安全预算,不只花在“拒绝非法输入”上,也花在“用多贵的计算去发现它是非法的”。上限设在哪里,决定了攻击者的成本。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:云梦安全 云梦DC 云梦DC《hpack:一个畸形头部块,如何拖垮 HTTP/2 解析线程》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论