本文详细分析了curl库中一个Use-After-Free漏洞的技术细节,该漏洞在某些版本中可导致任意写入,文章涵盖漏洞原理、复现步骤、影响版本及修复方案,涉及内存管理、splay树操作等底层技术实现。
curl Use-After-Free漏洞技术分析
漏洞概述
该漏洞是一个Use-After-Free(释放后使用)漏洞,在某些curl版本中可导致任意写入/读取内存。漏洞存在于curl处理并行传输(-Z选项)和URL通配符([0-10]格式)时的内存管理逻辑中。
受影响版本
- curl 8.13.0 (x86_64-pc-linux-gnu) - 可导致任意读/写
- curl 8.14.0 (x86_64-pc-linux-gnu) - 可导致任意读/写
- curl 8.15.0 (x86_64-pc-linux-gnu) - 仅导致任意写入
漏洞复现步骤
- 下载并编译目标版本:
1
2
3
|
wget https://github.com/curl/curl/releases/download/curl-8_14_0/curl-8.14.0.zip && unzip curl-8.14.0.zip && cd curl-8.14.0
CFLAGS="-fsanitize=address,undefined -g -O0 -fno-omit-frame-pointer" ./configure --with-openssl
make all -j$(nproc) && sudo make install
|
- 触发漏洞:
1
|
while true; do curl --url "c071993_domain22.com/image[0-10]tp.com/dir[0-10]/api/path[0-10]/api" -Zs --max-time 0.01; echo $?; done
|
技术原理
漏洞触发路径
curl_easy_init()
调用Curl_open()
分配Curl_easy
结构体
- 传输完成后
post_per_transfer()
调用curl_easy_cleanup()
,进而调用Curl_close()
释放内存
Curl_expire_clear()
调用Curl_splayremove()
时传入已释放的&data->state.timenode
指针
Curl_splayremove()
对已释放内存进行指针操作(splay.c:234行),导致UAF和任意写入
关键代码片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 内存分配
struct Curl_easy *data = calloc(1, sizeof(struct Curl_easy));
// 内存释放
free(data); // struct Curl_easy *data被释放但未置空
// UAF发生点
int Curl_splayremove(struct Curl_tree *t,
struct Curl_tree *removenode, // 已释放的&data->state.timenode
struct Curl_tree **newroot)
{
removenode->samep->samen = removenode->samen; // splay.c:234行,写入已释放内存
removenode->samen->samep = removenode->samep;
}
|
漏洞条件
- 必须使用URL通配符(方括号范围格式)
- 需要启用并行模式(-Z选项)
- –max-time设置为较小值(如0.01)
修复方案
在curl 8.15.0中通过修改multi.c的curl_multi_perform()
函数修复:
1
2
3
4
5
6
7
8
9
10
|
+ (void)add_next_timeout(now, multi, data);
if(data->mstate == MSTATE_PENDING) {
bool stream_unused;
CURLcode result_unused;
if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) {
infof(data, "PENDING handle timeout");
move_pending_to_connect(multi, data);
}
}
- (void)add_next_timeout(now, multi, Curl_splayget(t));
|
影响分析
虽然该漏洞理论上可导致8字节任意写入,但实际利用面临以下挑战:
- 攻击者需要精确控制堆内存布局
- 依赖特定网络时序条件
- 写入内容不可控(仅为内部splay树操作)
参考链接