网货帮
41.82MB · 2026-02-20
在 curl 的 TFTP 协议实现中发现了一个漏洞,该漏洞可能导致 curl 或使用 libcurl 的应用程序在特定条件下,向恶意的 TFTP 服务器发送超出已分配内存块边界的内存数据。
该漏洞存在于 commit 3ee1d3b5 的 libcurl 中,具体位于 lib/tftp.c 文件的 tftp_send_first() 函数。
漏洞核心代码如下 (lib/tftp.c 文件,tftp_send_first() 函数,第467行附近):
1 if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
2 // [...]
3 }
4
5 curl_msnprintf((char *)state->spacket.data + 2,
6 state->blksize,
7 "%s%c%s%c", filename, ' ', mode, ' ');
8 sbytes = 4 + strlen(filename) + strlen(mode);
9
10 // [...]
11
12 senddata = sendto(state->sockfd, (void *)state->spacket.data,
13 (SEND_TYPE_ARG3)sbytes, 0,
14 CURL_SENDTO_ARG5(&remote_addr->curl_sa_addr),
15 (curl_socklen_t)remote_addr->addrlen);
当满足以下条件时,漏洞可以被触发:
--tftp-no-options 参数调用 curl,或者 libcurl 的使用者设置了 CURLOPT_TFTP_NO_OPTIONS 为 1。state->blksize) 协商为一个较小的值(例如 8)。mode 保持默认值 "octet"(长度为 5)。当这些条件满足时,第467行的边界检查代码会变成:
if(strlen(filename) > (8 /* state->blksize */ - 5 /* strlen(mode) */ - 4)) {
计算 8 - 5 - 4 = -1,导致一个整数下溢。这使得检查条件的结果总是为 false,即使文件名非常长,原本的边界检查也会被绕过。
随后,第8行根据文件名的实际长度计算要发送的字节数 (sbytes),但这个长度可能已经超过了已分配的缓冲区大小。紧接着的第12行 sendto 调用就可能发送超出缓冲区边界的数据。
此漏洞的潜在影响是信息泄露,即可能将堆内存中的内容发送给恶意的 TFTP 服务器。
然而,curl 的开发团队在评估后认为,该漏洞的严重性为 LOW(低),甚至仅被视为一个普通的 Bug。主要原因如下:
curl 的开发团队已经修复了此问题。修复的 Pull Request 为:github.com/curl/curl/p…
修复的核心在于修正了边界检查的逻辑,避免整数下溢的发生。
修复代码示例:
- if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
+ if(strlen(filename) + strlen(mode) + 4 > state->blksize) {
failf(data, "TFTP filename too long");
curlx_free(filename);
return CURLE_TFTP_ILLEGAL; /* too long filename field */
}
- curl_msnprintf((char *)state->spacket.data + 2,
- state->blksize,
- "%s%c%s%c", filename, ' ', mode, ' ');
- sbytes = 4 + strlen(filename) + strlen(mode);
+ sbytes = 2 +
+ curl_msnprintf((char *)state->spacket.data + 2,
+ state->blksize,
+ "%s%c%s%c", filename, ' ', mode, ' ');
curlx_free(filename);
新的代码通过将各部分长度相加后再与缓冲区大小进行比较,从根本上杜绝了整数下溢的可能性。同时,sbytes 的计算也改为基于 curl_msnprintf 的实际返回值,更加准确和安全。FINISHED
biOK/hzhVF2yKaGc5mK8oeejIYuUYW8I3RsXQCFCiXXSrEl8bonoS+c8zsMSKu1g