深入解析libcurl HTTP/2 PUSH_PROMISE帧处理中的堆缓冲区越界读取漏洞

本文详细分析了一份关于libcurl库lib/http2.c文件中on_header回调函数在处理HTTP/2 PUSH_PROMISE帧时可能存在的堆缓冲区越界读取漏洞报告。报告最初认为使用%s格式符处理非空终止字符串会导致内存越界读取或敏感信息泄露,但最终经维护者澄清,nghttp2库保证了字符串的空终止,因此该报告被判定为无效。

堆缓冲区越界读取漏洞报告分析: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 回调中提供的 namevalue 指针指向的数据并非空终止字符串。因此,使用 %s 格式说明符(而没有指定精度,例如 %.*s)会导致 curl_maprintf 函数越界读取已分配缓冲区之外的内存,直到在堆内存中遇到空字节为止。

潜在影响

  1. 拒绝服务:可能导致客户端因内存耗尽(OOM)或无效读取而崩溃。
  2. 信息泄露:可能将相邻的堆数据泄露到头部字符串中,这些数据可能被应用程序处理或记录。

技术细节与复现步骤

受影响版本:在最新的 master 分支(提交 752d… / curl 8.6.0-dev)上复现。平台:Linux(使用 ASAN 构建复现)。

复现步骤概述

  1. 编译带有地址消毒器(ASAN)的 curl
    1
    2
    
    ./configure --enable-debug --enable-curldebug --with-nghttp2 --with-openssl CFLAGS="-fsanitize=address -g -O0" LDFLAGS="-fsanitize=address"
    make -j4
    
  2. 设置恶意的 Python HTTP/2 服务器。该服务器发送一个包含特定负载(例如长字符串头部)的 PUSH_PROMISE 帧。报告提供了一个使用 h2 库的 Python 脚本 (repro.py)。
  3. 运行攻击:启动恶意服务器,然后使用编译好的 curl 客户端(确保启用 HTTP/2 服务器推送)连接至该服务器。
  4. 观察结果:预期 curl 进程会因 ASAN 报告而崩溃,或返回错误 -902(用户回调函数失败)。

建议的修复:将 curl_maprintf 调用修改为使用 nghttp2 提供的长度和精度说明符:

1
h = curl_maprintf("%.*s:%.*s", (int)namelen, name, (int)valuelen, value);

项目维护者响应与调查

curl 维护者 bagder (Daniel Stenberg) 对报告提出了关键性质疑。

核心反驳点bagder 引用了 nghttp2 库的源代码(nghttp2_hd.h),其中 nghttp2_hd_nv 结构体的定义明确指出:

1
2
3
4
5
6
typedef struct {
  /* The buffer containing header field name.  NULL-termination is guaranteed. */
  nghttp2_rcbuf *name;
  /* The buffer containing header field value.  NULL-termination is guaranteed. */
  nghttp2_rcbuf *value;
  ...

这意味着,在 on_header 回调被调用时,namevalue 指针所指向的数据已经由底层的 nghttp2 库保证了空终止。因此,使用 %s 格式说明符是安全的,不存在越界读取的风险。

报告后续与结论

在维护者提供了确凿的代码证据后,报告人 efrsxcv 进行了深入的验证:

“我使用调试构建进行了深入验证,以检查 nghttp2 回调边界处的原始内存。您完全正确——在到达此回调之前,底层库确实已经对名称和值指针进行了空终止,这使得 %s 的使用是安全的。我最初基于缺少精度说明符的假设是一个误报。”

最终状态

  • 报告人主动关闭了报告,并将其状态标记为 无效/仅供参考
  • 维护者随后将报告状态更改为 不适用,并评论道:“这不被认为是一个安全问题。”
  • 根据项目的透明度政策,该报告被请求并最终公开披露

报告元数据

  • 报告ID: #3480078
  • 报告时间: 2025年12月27日
  • 公开时间: 2025年12月28日
  • 初始严重性评级: 高 (7 ~ 8.9)
  • 弱点类型: 缓冲区越界读取
  • CVE ID: 无
  • 漏洞赏金: 无

关键启示

此案例凸显了在开源软件安全研究中准确理解依赖库(此处为 nghttp2)的接口契约和行为的重要性。报告人的初步分析基于对接口文档的特定解读,但未能验证底层库的实际实现保证。维护者通过直接引用依赖库的源代码,迅速澄清了误解,避免了不必要的修复工作,并维护了代码的稳定性。这也展示了负责任的安全披露流程中,维护者与研究者之间建设性对话的价值。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计