深入解析:cURL库TFTP实现中的堆缓冲区溢出漏洞

报告详细描述了libcurl的TFTP实现中存在的一个堆缓冲区溢出漏洞。当恶意TFTP服务器发送包含大于默认块大小(512字节)的blksize选项的OACK数据包时,会触发此漏洞。此漏洞可能导致远程代码执行或拒绝服务攻击。

时间线

  • helspy 向 curl 项目提交了一份报告。 (5天前)
  • bagder (curl 工作人员) 发表评论。 (5天前)
  • bagder (curl 工作人员) 发表评论。 (5天前)
  • helspy 发表评论。 (5天前)
  • helspy 发表评论。 (5天前)
  • bagder (curl 工作人员) 关闭了报告并将状态更改为“不适用”。 (4天前)
  • bagder (curl 工作人员) 请求公开此报告。 (4天前)
  • bagder (curl 工作人员) 公开了此报告。 (4天前)

报告摘要

libcurl 的 TFTP 实现中存在一个堆缓冲区溢出漏洞。当恶意的 TFTP 服务器发送一个带有 blksize 选项的 OACK(选项确认)数据包,且该选项的值大于默认块大小(512 字节)时,会触发此漏洞。libcurl 更新了其内部的块大小变量,但未能重新分配接收和发送缓冲区(rpacketspacket)。当应用程序随后使用更大的块大小接收数据(在 tftp_rx 中)或发送数据(在 tftp_tx 中)时,会写入超出已分配缓冲区的末尾,从而导致堆缓冲区溢出。

受影响版本

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

复现步骤

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

支持材料/参考

  • 易受攻击的代码位置: lib/tftp.c, 函数: tftp_parse_option_ack
    • 更新了 state->blksize 但未重新分配 state->spacket.datastate->rpacket.data
  • 复现脚本: tftp_repro.py

影响

  • 摘要: 此漏洞允许恶意的 TFTP 服务器在客户端引发堆缓冲区溢出。
  • 远程代码执行(RCE): 通过精心构造 DATA 数据包中的负载,攻击者可以覆盖关键的堆元数据或函数指针,可能导致在受害者机器上以 curl 进程的权限执行任意代码。
  • 拒绝服务(DoS): 溢出可能破坏内存结构,导致 curl 应用程序崩溃或行为不可预测,从而造成拒绝服务。

评论记录

  • bagder (curl 工作人员) 评论 (5天前):

    感谢您的报告! 我们将花一些时间调查您的报告,并尽快给您回复详情和可能的后续问题!很可能在接下来的 24 小时内。 我们始终致力于尽快修复报告的问题。严重性为低或中等问题我们将在常规发布周期中合并到下一个版本。只有对于更严重的问题,我们才可能提前发布修复。

  • bagder (curl 工作人员) 评论 (5天前):

    @helspy 没有附加 tftp_repro.py 脚本?

  • helspy 评论 (5天前):

    抱歉!这是程序…

     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
    
    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()
    
  • helspy 评论 (5天前):

    看起来在 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;
    }
    

    此检查强制客户端使用大于最初分配的块大小,因此可能防止了堆溢出。

  • bagder (curl 工作人员) 关闭了报告并将状态更改为“不适用”。 (4天前):

    认为这不是一个安全问题。

  • bagder (curl 工作人员) 请求公开此报告。 (4天前):

    根据项目透明度政策,我们希望所有报告都被公开并公之于众。

  • bagder (curl 工作人员) 公开了此报告。 (4天前)

报告详情

  • 报告时间: 2025年11月29日,下午5:06 (UTC)
  • 报告者: helspy
  • 报告给: curl
  • 参与者:
    • Reported on November 29, 2025, 5:06pm UTC
    • Reported by helspy
    • Reported to curl
  • 报告 ID: #3444904
  • 严重性: 严重 (9 ~ 10)
  • 公开时间: 2025年12月1日,上午7:41 (UTC)
  • 弱点: 堆溢出
  • CVE ID:
  • 赏金:
  • 账户详情:
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计