curl配置文件解析中的任意释放漏洞分析

本文详细分析了在curl配置文件解析过程中发现的一个漏洞,该漏洞可导致任意地址被释放,进而可能引发双重释放或释放后使用等内存安全问题。报告包含详细的复现步骤、调试信息以及项目维护者的修复讨论。

curl配置文件解析中的任意释放漏洞

摘要: 本文分析了一个在curl工具配置文件解析过程中发现的漏洞。该漏洞允许攻击者通过精心构造的配置文件,控制传递给free()函数的指针地址,可能导致双重释放、释放后使用或内存损坏。报告包含了详细的复现步骤、GDB调试记录以及项目维护者提供的修复补丁和讨论。

漏洞概述

在curl解析包含特定畸形URL的配置文件时,tool_urlglob.c文件中的glob_cleanup函数可能释放一个未初始化或由攻击者部分控制的堆内存指针。这为攻击者提供了一个潜在的入口点,可能绕过某些安全控制机制。

受影响版本

  • curl 8.17.0 (x86_64-pc-linux-gnu)
  • curl 8.16.0 也受到影响,配置文件中的可控参数和样本可能不同。

测试环境: Linux kali 6.3.0-kali1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.3.7-1kali1。

复现步骤

  1. 创建配置文件 host0.bin,内容如下:
    1
    2
    3
    4
    
    --url "http://google.com/iernay{1-2}kFORFNUUklOR1JBTkRTVFJJTkdSQU5EU1RSSU5HUkFORFNUUklOR1JBTkRTVFJJTkdSQU5EU1RSSU5HUkFORFNUUklOR1JBTkRTVFJJT"
    --url "http://[::%2-socks5]:8080/"
    --url google.com-Z[.-p].example.com"
    --doh-url=127.0.0.1
    
  2. 运行命令: gdb -ex "r" --args curl --config host0.bin
  3. 程序会在__GI___libc_free函数中因访问非法地址 (0x2e302e302e373231,即"127.0.0.") 而触发段错误。

控制传递到free()的指针: 报告者提供了一个Python脚本mutate.py,用于修改配置文件,将可控数据(例如0x4242424242424242)写入配置文件,从而控制传递给free()函数的指针。使用修改后的配置文件vuln.conf运行curl,可以在GDB中观察到free()被调用时,rdi寄存器指向攻击者指定的地址 (0x4242424242424242)。

触发双重释放: 通过将已被释放的堆地址(例如0x555555602dd0)写入配置文件,可以触发glibc的tcache双重释放检测机制,导致程序中止并输出错误信息:free(): double free detected in tcache 2

漏洞分析

漏洞位于 src/tool_urlglob.c 文件的 glob_cleanup 函数中。在特定错误路径下,glob->pattern[i].c.set.elem[elem]可能指向未初始化或已被部分覆盖的堆内存。当程序清理资源调用tool_safefree()(最终调用free())时,便会传递这个受控或无效的指针。

关键代码段 (glob_cleanup):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if(glob->pattern) {
  for(i = 0; i < glob->size; i++) {
    if((glob->pattern[i].type == GLOB_SET) &&
       (glob->pattern[i].c.set.elem)) {
      for(elem = glob->pattern[i].c.set.size - 1; elem >= 0; --elem)
        tool_safefree(glob->pattern[i].c.set.elem[elem]); // 漏洞点
      tool_safefree(glob->pattern[i].c.set.elem);
    }
  }
  tool_safefree(glob->pattern);
}

利用限制与讨论

  • 利用前提: 需要诱使用户运行恶意的curl配置文件(例如通过~/.curlrc或直接指定--config)。
  • 安全影响: curl本身已具备执行命令的能力(例如通过--output写入文件或配合其他机制)。此漏洞提供了另一种潜在的、非预期的攻击路径。报告者认为,如果存在针对恶意配置文件的特定安全控制或净化器,此漏洞可能绕过它们。
  • 利用复杂度: 要成功利用此漏洞实现代码执行,攻击者需要:
    1. 绕过ASLR(地址空间布局随机化)。
    2. 绕过glibc的tcache双重释放缓解机制。
    3. 精心构造内存布局,使后续的malloc()返回攻击者控制的“伪造”块,这需要深入的堆内存操作知识。

项目维护者反馈与修复

curl安全团队(bagder, dgustafsson)审查了此报告。

  • 初步评估: 维护者认为这是一个工具中的bug,而非安全漏洞。理由是curl工具作为单进程运行在用户权限下,攻击者能通过恶意配置文件造成的危害(如崩溃)与curl本身已有的能力(如执行命令)相比,并未增加新的风险。
  • 修复补丁: 尽管不视为安全漏洞,维护者仍然提供了修复代码。最初的补丁不完整,后续提交了更完善的修复(GitHub PR #19614),主要修正了glob_parse函数中的错误处理逻辑,确保在分配失败时正确清理,避免访问未初始化的内存。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    --- a/src/tool_urlglob.c
    +++ b/src/tool_urlglob.c
    @@ -418,11 +418,11 @@ static CURLcode glob_parse(struct URLGlob *glob, const char *pattern,
            res = glob_range(glob, &pattern, &pos, amount, globindex++);
            break;
          }
        }
    -    if(++glob->size >= glob->palloc) {
    +    if(!res && (++glob->size >= glob->palloc)) { // 仅在解析成功时尝试扩容
            struct URLPattern *np = NULL;
            glob->palloc *= 2;
            if(glob->size < 255) { /* avoid ridiculous amounts */
                np = realloc(glob->pattern, glob->palloc * sizeof(struct URLPattern));
                if(!np)
    

总结

本报告展示了一个curl工具中由配置文件解析引发的内存安全缺陷。虽然curl维护团队出于“未证明可造成实际安全危害”的考虑将其定性为普通bug,但它清晰地揭示了在复杂命令行工具的输入解析过程中,内存管理错误可能带来的风险。对于安全研究人员和开发者而言,此类问题仍值得关注,因为它们可能在特定环境或与其他漏洞结合时产生安全影响。

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