堆缓冲区越界读取漏洞报告分析:libcurl中PUSH_PROMISE帧处理
报告摘要
报告人 efrsxcv 提交了一份关于 libcurl 中潜在堆缓冲区越界读取漏洞的报告。该漏洞涉及 lib/http2.c 文件中的 on_header 回调函数,具体在处理 HTTP/2 PUSH_PROMISE 帧时。
核心指控:报告指出,在 on_header 函数中,代码使用 curl_maprintf("%s:%s", name, value); 来格式化头部名称和值。根据 nghttp2 的文档,on_header 回调中提供的 name 和 value 指针指向的数据并非空终止字符串。因此,使用 %s 格式说明符(而没有指定精度,例如 %.*s)会导致 curl_maprintf 函数越界读取已分配缓冲区之外的内存,直到在堆内存中遇到空字节为止。
潜在影响:
- 拒绝服务:可能导致客户端因内存耗尽(OOM)或无效读取而崩溃。
- 信息泄露:可能将相邻的堆数据泄露到头部字符串中,这些数据可能被应用程序处理或记录。
技术细节与复现步骤
受影响版本:在最新的 master 分支(提交 752d… / curl 8.6.0-dev)上复现。平台:Linux(使用 ASAN 构建复现)。
复现步骤概述:
- 编译带有地址消毒器(ASAN)的 curl。
1 2./configure --enable-debug --enable-curldebug --with-nghttp2 --with-openssl CFLAGS="-fsanitize=address -g -O0" LDFLAGS="-fsanitize=address" make -j4 - 设置恶意的 Python HTTP/2 服务器。该服务器发送一个包含特定负载(例如长字符串头部)的 PUSH_PROMISE 帧。报告提供了一个使用
h2库的 Python 脚本 (repro.py)。 - 运行攻击:启动恶意服务器,然后使用编译好的 curl 客户端(确保启用 HTTP/2 服务器推送)连接至该服务器。
- 观察结果:预期 curl 进程会因 ASAN 报告而崩溃,或返回错误
-902(用户回调函数失败)。
建议的修复:将 curl_maprintf 调用修改为使用 nghttp2 提供的长度和精度说明符:
|
|
项目维护者响应与调查
curl 维护者 bagder (Daniel Stenberg) 对报告提出了关键性质疑。
核心反驳点:bagder 引用了 nghttp2 库的源代码(nghttp2_hd.h),其中 nghttp2_hd_nv 结构体的定义明确指出:
|
|
这意味着,在 on_header 回调被调用时,name 和 value 指针所指向的数据已经由底层的 nghttp2 库保证了空终止。因此,使用 %s 格式说明符是安全的,不存在越界读取的风险。
报告后续与结论
在维护者提供了确凿的代码证据后,报告人 efrsxcv 进行了深入的验证:
“我使用调试构建进行了深入验证,以检查 nghttp2 回调边界处的原始内存。您完全正确——在到达此回调之前,底层库确实已经对名称和值指针进行了空终止,这使得
%s的使用是安全的。我最初基于缺少精度说明符的假设是一个误报。”
最终状态:
- 报告人主动关闭了报告,并将其状态标记为 无效/仅供参考。
- 维护者随后将报告状态更改为 不适用,并评论道:“这不被认为是一个安全问题。”
- 根据项目的透明度政策,该报告被请求并最终公开披露。
报告元数据:
- 报告ID: #3480078
- 报告时间: 2025年12月27日
- 公开时间: 2025年12月28日
- 初始严重性评级: 高 (7 ~ 8.9)
- 弱点类型: 缓冲区越界读取
- CVE ID: 无
- 漏洞赏金: 无
关键启示
此案例凸显了在开源软件安全研究中准确理解依赖库(此处为 nghttp2)的接口契约和行为的重要性。报告人的初步分析基于对接口文档的特定解读,但未能验证底层库的实际实现保证。维护者通过直接引用依赖库的源代码,迅速澄清了误解,避免了不必要的修复工作,并维护了代码的稳定性。这也展示了负责任的安全披露流程中,维护者与研究者之间建设性对话的价值。