Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-3805-curl-SMB-UAF — CVE-2026-3805: curl的SMB连接重用中的释放后使用漏洞 - 堆信息泄露 | Kitploit
工具/GitHubGitHub/rat5ak/cve-2026-3805-curl-smb-uaf
内存取证漏洞分析漏洞利用二进制分析论文与研究学习与教育
GitHubrat5ak/cve-2026-3805-curl-smb-uaf

CVE-2026-3805-curl-SMB-UAF

CVE-2026-3805: curl的SMB连接重用中的释放后使用漏洞 - 堆信息泄露

查看仓库
122个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-3805:curl SMB 连接复用中的释放后使用

我在 libcurl 的 SMB 协议处理器中发现了一个释放后使用漏洞。当第二次 SMB 传输重用与同一服务器的现有连接时,新请求的文件路径(req->path)成为一个指向已释放堆内存的悬空指针。该内存通过 strlen() 读取并复制到外发的 SMB 数据包中,导致堆内容泄露给服务器或崩溃。

一行修复:让 req->path 拥有自己的副本,而不是借用 needle 中 smbc->share 的指针。

CVECVE-2026-3805
漏洞类型释放后使用(CWE-416)
根本原因req->path 指向 needle 的 smbc->share,连接复用时被释放
引入版本777c5209df(2025-04-30)- curl 8.13.0
修复版本e090be9f73a7a71459ef678c - curl 8.19.0(2026年3月11日)
受影响版本curl 8.13.0 至 8.18.0
影响服务器获取堆信息泄露,崩溃
严重程度7.5 - 高 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

TL;DR

smb_setup_connection() 在一个用于缓存查找的临时 "needle" 连接上运行。它将 req->path 设置为指向 smbc->share(needle 拥有的堆内存)内部。当连接缓存找到可复用的连接时,needle 被销毁 - 释放 smbc->share - 但 req->path 仍存在于 easy handle 上,现在成为悬空指针。

当 smb_send_open() 构建 SMB OPEN 请求时,它调用 strlen(req->path) 并将结果复制到外发数据包中。该已释放堆区域中的任何数据都会发送到服务器。如果攻击者控制服务器(SSRF,或用户连接到恶意 SMB),他们将通过 SMB NT_CREATE_ANDX 请求中的“文件名”接收到泄露的堆内容。


背景:curl 连接复用

libcurl 积极复用连接以提高性能。当你向同一主机发出多个请求时,curl 会检查是否复用现有连接,而不是建立新连接。机制如下:

  1. 使用新请求的参数创建一个临时的 "needle" 连接
  2. 在连接缓存中搜索匹配的连接
  3. 如果找到:复用现有连接,销毁 needle
  4. 如果未找到:needle 成为实际连接

SMB 协议处理器在两个位置存储状态:

  • smbc(连接状态)在连接的 meta_hash 上
  • req(请求状态)在 easy handle 的 meta 上

漏洞:在 needle 设置期间,req->path 被设置为指向 smbc->share 内部。当 needle 在复用时被销毁,smbc->share 被释放,但 req->path 仍然指向那里。

漏洞

在 smb_parse_url_path() 中,代码解析 SMB URL 路径并将其拆分为共享名和文件路径:

root@kitploit:~
// lib/smb.c, smb_parse_url_path() line 431:
smbc->share = curlx_strdup((*path == '/' || *path == '\\') ? path + 1 : path);
// ...
*slash++ = 0;
req->path = slash;   // <--- 指向 NEEDLE 上的 smbc->share

对于 URL smb://server/share1/file1.txt,这会创建:

  • smbc->share = "share1\0file1.txt"(堆分配,由 needle 拥有)
  • req->path = 指向 "file1.txt" 的指针(在 smbc->share 内部)

当连接复用时:

root@kitploit:~
// lib/url.c, url_find_or_create_conn() line 3619:
out:
  if(needle)
    Curl_conn_free(data, needle);  // 销毁 needle -> 释放 smbc->share

Curl_conn_free() 调用 Curl_hash_destroy(&conn->meta_hash),后者调用 smb_conn_dtor(),释放 smbc->share。但 req->path(位于易失的 easy handle 上)仍然指向现在已释放的内存。

当 SMB 请求继续进行时:

root@kitploit:~
// lib/smb.c, smb_send_open() line 750-769:
const size_t byte_count = strlen(req->path) + 1;    // 释放后读取
// ...
curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1);  // 释放后读取

影响

信息泄露

已释放的堆内存可能被重新分配并包含敏感数据。strlen(req->path) 会向前扫描直到遇到空字节,curlx_strcopy() 将该内容复制到发送给服务器的 SMB 数据包中。

攻击场景:攻击者控制 SMB 服务器的 SSRF。受害者应用程序向攻击者的服务器发出两次 SMB 请求。第二次请求将堆内容作为 SMB OPEN 请求中的“文件名”泄露。

拒绝服务

如果已释放的内存已归还给操作系统(未映射),strlen() 会触发 SIGSEGV/访问违规。

次要漏洞:错误的共享名

即使没有释放后使用,SMB 连接复用在语义上也是错误的。smb_send_tree_connect() 使用的是 复用 连接(旧共享名)中的 smbc->share,而不是新请求的共享名。TREE_CONNECT 会指向完全错误的共享名。


复现

通过 curl CLI

root@kitploit:~
# 指向同一服务器的两个 SMB URL,不同共享名/文件:
curl smb://192.168.1.100/share1/file1.txt -o /dev/null \
     smb://192.168.1.100/share2/file2.txt -o /dev/null

通过 libcurl(multi-handle)

root@kitploit:~
CURLM *multi = curl_multi_init();

CURL *e1 = curl_easy_init();
curl_easy_setopt(e1, CURLOPT_URL, "smb://server/share1/file1");
curl_multi_add_handle(multi, e1);

CURL *e2 = curl_easy_init();
curl_easy_setopt(e2, CURLOPT_URL, "smb://server/share2/file2");
curl_multi_add_handle(multi, e2);

// 当 e2 在 e1 完成后运行并复用连接时:发生释放后使用

使用 AddressSanitizer

使用 -fsanitize=address 构建 curl 并运行上述代码:

root@kitploit:~
==PID==ERROR: AddressSanitizer: heap-use-after-free on address 0x...
READ of size 1 at 0x... thread T0
    #0 strlen
    #1 smb_send_open lib/smb.c:750
    #2 smb_request_state lib/smb.c:1163
    ...

freed by thread T0 here:
    #0 free
    #1 smb_conn_dtor lib/smb.c:388
    #2 Curl_hash_destroy
    #3 Curl_conn_free lib/url.c:557

参见 poc/REPRODUCE_UAF.sh 获取完整复现脚本。


修复

根本问题是 req->path 借用了指向 needle 的 smbc 所拥有内存的指针。修复让 req->path 拥有自己的副本:

root@kitploit:~
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -378,7 +378,7 @@ static void smb_easy_dtor(void *key, size_t klen, void *entry)
   (void)key;
   (void)klen;
+  curlx_free(req->path);
   curlx_free(req);
 }

@@ -428,7 +428,10 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data,
   /* 将任何正斜杠转换为反斜杠,解析文件路径 */
   *slash++ = 0;
-  req->path = slash;
+  req->path = curlx_strdup(slash);
+  if(!req->path) {
+    Curl_safefree(smbc->share);
+    return CURLE_OUT_OF_MEMORY;
+  }

Stefan Eissing 在 e090be9f73a7a71459ef678c 中实现了官方修复。


开发者意识

开发者可能部分意识到了悬空指针的风险。smb_easy_dtor() 中存在以下注释:

root@kitploit:~
/* `req->path` 指向 `struct smb_conn` 中的某处,该结构位于连接元数据中。
 * 如果连接先被销毁,req->path 将指向已释放的内存。 */

但这只考虑了连接在 easy handle 之前销毁的场景,而遗漏了 连接复用时 needle 销毁 的场景,而这正是实际的触发条件。


时间线

日期事件
2025-04-30777c5209df 重构 SMB 以使用元哈希,引入了该漏洞

受影响的配置

  • SMB 必须启用:!defined(CURL_DISABLE_SMB)
  • NTLM 核心必须可用:defined(USE_CURL_NTLM_CORE)
  • sizeof(curl_off_t) > 4(64 位 off_t,大多数平台标准)

在具有 NTLM 支持的 curl 构建中,SMB 默认启用。


资源

  • 修复提交:e090be9f73a7a71459ef678c
  • 官方公告:curl.se/docs/CVE-2026-3805.html
  • HackerOne 报告:#3591944
  • 引入提交:777c5209df

CVE-2026-3805 - 已在 curl 8.19.0 中修复。受影响版本:8.13.0 至 8.18.0。

Daniel Wade - GitHub - [email protected]

下载工具
2026-03-07我在安全审计中发现该漏洞
2026-03-08通过 HackerOne 报告给 curl(#3591944)
2026-03-08curl 联系 distros@openwall
2026-03-11curl 8.19.0 发布,包含修复,CVE-2026-3805 公布