curl schannel.c TLS整数溢出漏洞分析与复现

本文详细分析了curl库中schannel.c文件存在的整数溢出漏洞,该漏洞在TLS加密数据传输过程中可能导致数据大小计算错误和安全问题,包含完整的PoC代码和测试环境搭建指南。

curl schannel.c TLS数据传输整数溢出漏洞

漏洞摘要

该漏洞允许在加密数据传输过程中添加TLS缓冲区大小时发生整数溢出,可能导致发送错误的数据大小和TLS安全问题。在Windows 10测试环境中,Windows的Schannel拒绝了构造的畸形TLS握手(SEC_E_INVALID_TOKEN),这与预期一致。

技术细节

漏洞位于./lib/vtls/schannel.c文件中的以下代码:

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

curl将三个缓冲区相加:outbuf[0](TLS头)、outbuf[1](加密数据)和outbuf[2](TLS尾部)。curl在没有检查整数溢出的情况下将这三个值相加,在32位测试环境中,如果大小足够大,加法可能溢出,导致len值变小。

影响范围

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

复现步骤

编译恶意服务器(32位)

1
i686-w64-mingw32-gcc -Wall -Wextra -g3 malicious_server.c -o malicious_server.exe -lws2_32

测试命令

1
curl -k https://localhost:4433/

PoC代码

数学验证PoC

 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
#define SECURITY_WIN32 1
#include <windows.h>
#include <security.h>
#include <schannel.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Curl Schannel Integer Overflow PoC\n");
    printf("==================================\n\n");

    SYSTEM_INFO si;
    GetSystemInfo(&si);
    printf("Architecture: %s\n", si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? "64-bit" : "32-bit");
    printf("sizeof(size_t): %llu bytes\n\n", (unsigned long long)sizeof(size_t));

    SecBuffer outbuf[3];
    outbuf[0].cbBuffer = 0x80000000;
    outbuf[1].cbBuffer = 0x80000001;
    outbuf[2].cbBuffer = 0x00000000;

    size_t len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;

    printf("Vulnerable code: len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer\n\n");
    printf("0x%08lX + 0x%08lX + 0x%08lX = 0x%llX\n", 
           (unsigned long)outbuf[0].cbBuffer,
           (unsigned long)outbuf[1].cbBuffer, 
           (unsigned long)outbuf[2].cbBuffer,
           (unsigned long long)len);

    unsigned long long expected = 0x100000001ULL;

    if(sizeof(size_t) == 4 && len != expected) {
        printf("\n*** INTEGER OVERFLOW on 32-bit! ***\n");
        printf("Expected: %llu bytes\n", expected);
        printf("Got: %llu bytes\n", (unsigned long long)len);
    }

    return 0;
}

影响版本

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

实际影响

攻击者可以通过TLS传输凭据时实现认证绕过,或者通过操纵TLS握手来阻止数据泄露。这还可能导致DoS攻击,因为当len值很小时可能出现无限循环,或者由于协议违规导致连接完全挂起。

讨论记录

项目维护者对漏洞的实际可利用性表示怀疑,认为在典型的Windows环境中不会触发此漏洞,因为Schannel会提前阻止尝试。最终报告状态被标记为"不适用",但为了透明度而公开披露。

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