栈使用后释放漏洞:libcurl HTTP/3 POST请求处理中的CURLOPT_POSTFIELDS问题
摘要
libcurl的HTTP/3请求处理在使用CURLOPT_POSTFIELDS与栈分配缓冲区时存在栈使用后释放漏洞。libcurl保留用户提供的POST数据指针,但在原始栈帧销毁后访问该指针,导致内存损坏和潜在拒绝服务。
漏洞详情
漏洞存在于Curl_pretransfer()(transfer.c:569),当libcurl对先前存储的POST数据指针调用strlen()时,该指针现已指向无效的栈内存。
复现步骤/概念验证
环境
- libcurl版本:8.16.0-DEV(master分支)
- 编译器:带AddressSanitizer的Clang 20.1.8
- 平台:macOS(ARM64)
- 配置:启用HTTP/3(使用ngtcp2/nghttp3)
复现步骤
- 使用ASAN构建libcurl:
1
2
3
4
|
export CC=clang
export CFLAGS="-O1 -g -fsanitize=address,undefined"
./configure --with-openssl --with-nghttp2 --with-nghttp3 --with-ngtcp2
make
|
- 编译复现程序:
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
|
// http3_crash_poc.c
#include <curl/curl.h>
#include <string.h>
int main() {
CURL *curl = curl_easy_init();
// 栈分配缓冲区,超出作用域
{
char body_data[257];
memset(body_data, 'A', 256);
body_data[256] = '\0';
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_data); // 漏洞调用
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 50L);
} // body_data在此处超出作用域
// libcurl在传输期间访问无效内存
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
|
- 编译并运行:
1
2
|
clang -fsanitize=address http3_crash_poc.c -lcurl -o poc
./poc
|
崩溃输出
1
2
3
4
5
6
7
8
9
10
|
==3720==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016fa21470
READ of size 45 at 0x00016fa21470 thread T0
#0 strlen
#1 Curl_pretransfer transfer.c:569
#2 multi_runsingle multi.c:2376
#3 curl_multi_perform multi.c:2756
#4 easy_transfer easy.c:705
#5 easy_perform easy.c:813
SUMMARY: AddressSanitizer: stack-use-after-scope transfer.c:569 in Curl_pretransfer
|
技术分析
根本原因
漏洞源于libcurl的CURLOPT_POSTFIELDS行为:
- libcurl存储指针但不复制数据
- 应用程序的栈缓冲区在作用域退出后变为无效
- libcurl随后在Curl_pretransfer()中解引用无效指针
受影响代码路径
1
2
3
4
5
|
curl_easy_setopt(CURLOPT_POSTFIELDS) →
curl_easy_perform() →
Curl_pretransfer() →
strlen(invalid_pointer) →
崩溃
|
建议修复
- 文档说明:明确CURLOPT_POSTFIELDS数据必须在传输完成前保持有效
- API增强:考虑为栈检测指针添加边界检查或自动复制
- 替代API:推广CURLOPT_COPYPOSTFIELDS以实现更安全的使用模式
影响
安全影响
- 拒绝服务:保证崩溃导致应用程序终止
- 内存损坏:使用后释放可能导致不可预测行为
- 潜在代码执行:在特定情况下,内存损坏可能被利用进行控制流劫持
受影响场景
- 使用libcurl进行带POST数据的HTTP/3请求的应用程序
- 任何CURLOPT_POSTFIELDS指向栈分配内存的代码模式
- 特别影响:
- HTTP/3客户端应用程序
- 使用栈缓冲区作为请求体的API客户端
- 堆使用受限的嵌入式系统
实际暴露
- 语言绑定:许多curl绑定可能无意中创建此模式
- 示例应用程序:CLI工具、网络爬虫、API客户端
- 严重性:由于HTTP/3采用增长和远程可利用性而评为高
时间线
- geeknik 提交报告:10天前
- bagder(curl工作人员)回复:将调查报告
- bagder 进一步评论:CURLOPT_POSTFIELDS文档特别强调此行为,认为是用户错误而非libcurl缺陷
- geeknik 同意并关闭报告,状态改为"不适用"
- 报告已披露:10天前
报告详情
- 报告ID:#3279804
- 严重性:高(7 ~ 8.9)
- 披露时间:2025年7月31日 15:09 UTC
- 弱点类型:释放后使用
- CVE ID:无
- 赏金:隐藏
注意:根据curl团队反馈,此问题被认定为用户未遵循CURLOPT_POSTFIELDS文档要求所致,而非libcurl本身的安全漏洞。