深入解析:libcurl HTTP方法处理中的越界读取漏洞与修复方案

本文详细剖析了在libcurl核心HTTP处理中发现的一个内存安全漏洞。该漏洞源于HTTP方法字符串在复制时缺失空终止符,导致在HTTP/2请求转换和CONNECT方法检测时发生越界读取,可能引发未定义行为、程序崩溃或逻辑错误。

漏洞报告 #3434510 - HTTP方法处理中的越界读取导致未定义行为及潜在崩溃

报告人:gaurav_7777 (ID已验证) 提交日期:11天前 报告对象:curl

概要

  • 组件:libcurl 核心HTTP处理(HTTP/2请求转换和CONNECT检测)
  • 类型:因缺失空终止符导致的越界读取
  • 影响:行为不符合规范定义,程序可能崩溃(导致拒绝服务),且CONNECT请求可能被错误分类
  • 根本原因:方法字符串在复制时未添加空终止符

受影响的代码路径

结构体布局

1
struct httpreq { ... char method[1]; }

内存分配与复制(无空终止符)

1
2
req = calloc(1, sizeof(*req) + m_len);
memcpy(req->method, method, m_len);

不安全的使用

  • strcmp("CONNECT", req->method) —— 假设字符串以空字符结尾
  • strlen(req->method) —— 用于确定HTTP/2伪头部 :method 的大小

直接风险:如果 req->method[m_len] 越界,strcmpstrlen 都可能访问到分配内存之外的内容。具体影响因分配器/内存布局而异,但地址消毒器(ASan)总能检测到此问题。

复现步骤(简洁版)

前提:确保已安装 CMake 和 nghttp2。

  1. 检查版本:

    1
    2
    3
    4
    
    cmake --version
    # 输出示例:3.26.2
    pkg-config --modversion libnghttp2
    # 输出示例:1.52.0
    
  2. 使用 ASan 和 HTTP/2 支持编译 curl:

    1
    2
    
    mkdir -p build && cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS='-O1 -g -fsanitize=address' -DCMAKE_EXE_LINKER_FLAGS='-fsanitize=address' -DCURL_USE_NGHTTP2=ON
    cmake --build build -j"$(nproc)"
    
  3. 验证二进制文件和功能:

    1
    
    ./src/curl --version
    

影响

  • 拒绝服务/崩溃:在创建HTTP/2伪头部或检查CONNECT逻辑时发生越界读取。
  • 逻辑缺陷:用于检测CONNECT的方法可能因比较了未初始化的值而产生不同行为。

触发场景:任何生成 struct httpreq 实例(例如使用自定义HTTP方法)并随后执行HTTP/2转换或CONNECT检查的代码路径。

建议的修复方案(最小化且稳健)

在两个创建函数中,不仅添加空终止符,还为它分配内存:

代码变更示例

1
2
3
4
5
- req = calloc(1, sizeof(*req) + m_len);
+ req = calloc(1, sizeof(*req) + m_len + 1);
  if(!req) goto out;
  memcpy(req->method, method, m_len);
+ req->method[m_len] = '\0';
  • 需要修改的位置
    • Curl_http_req_make
    • Curl_http_req_make2

此变更消除了局部的未定义读取,且不改变原有逻辑。可选加固措施:替换 strcmp("CONNECT", ...)

后续讨论与状态更新

  1. bagder (curl 维护人员) 在11天前回复:感谢报告,团队将进行调查,通常在24小时内给出反馈。对于严重性较低的问题,会按常规发布周期修复;严重问题会提前发布修复。
  2. bagder 随后指出,报告者对根本原因的分析可能有误。由于结构体使用 calloc 分配,空终止符可能已经存在。
  3. icing (curl 团队成员) 确认:struct httpreqchar method[1]; 结尾,并且使用 calloc 分配了结构体大小加上 m_len 的内存,这为终止的空字节留出了空间。
  4. gaurav_7777 澄清并确认了其他报告的情况,承认此份报告因个人分析错误可能无效。
  5. bagder 将报告状态更改为“不适用”并关闭,指出这不是一个安全问题。但根据项目透明政策,所有报告完成后都将被公开披露。
  6. 经过沟通,gaurav_7777 最终同意披露此报告,并承诺未来将提供有效且高影响力的漏洞。

报告状态:已披露(2025年11月20日 UTC 时间 上午9:20) 严重性:高(7 ~ 8.9) 弱点:缓冲区过读 CVE ID:无 赏金:隐藏

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