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。
复现步骤
- 创建配置文件
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 - 运行命令:
gdb -ex "r" --args curl --config host0.bin - 程序会在
__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):
|
|
利用限制与讨论
- 利用前提: 需要诱使用户运行恶意的curl配置文件(例如通过
~/.curlrc或直接指定--config)。 - 安全影响: curl本身已具备执行命令的能力(例如通过
--output写入文件或配合其他机制)。此漏洞提供了另一种潜在的、非预期的攻击路径。报告者认为,如果存在针对恶意配置文件的特定安全控制或净化器,此漏洞可能绕过它们。 - 利用复杂度: 要成功利用此漏洞实现代码执行,攻击者需要:
- 绕过ASLR(地址空间布局随机化)。
- 绕过glibc的tcache双重释放缓解机制。
- 精心构造内存布局,使后续的
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,但它清晰地揭示了在复杂命令行工具的输入解析过程中,内存管理错误可能带来的风险。对于安全研究人员和开发者而言,此类问题仍值得关注,因为它们可能在特定环境或与其他漏洞结合时产生安全影响。