\n\n\n\n\n\n\n\n\n\n\n

flawopen.com/模拟沙箱/Heartbleed 内存越界模拟器

内存安全 / OpenSSL TLS

OpenSSL Heartbleed 缓冲区越界读取交互式模拟器 (CVE-2014-0160)

基于浏览器的交互式内存与数据包模拟器,直观展示未经验证的 TLS 心跳长度字段如何触发服务器堆内存越界越权读取。

💡 通俗易懂的解释 (ELI5)

想象你对一只受过训练的鹦鹉说了一个4个字母的单词“BIRD”,然后要求它:“复述这个词,但你的回答必须有64,000个字母长。”鹦鹉叫了声“BIRD”,随后立即开始喋喋不休地背诵它脑海记忆中的后63,996个字符——其中包括其他客人的机密密码、私钥和银行卡号。在 Heartbleed 漏洞中,OpenSSL 盲目信任客户端声称的消息长度,却未检查数据包的实际物理大小,从而将服务器私有堆内存直接拷贝回送给了攻击者。

核心概念与子系统术语

TLS Heartbeat 扩展
RFC 6520 定义的心跳保活机制,用于在无需重新握手的情况下测试安全通道。
\n
Payload 长度字段
心跳头部中的 16 位无符号整数,声明负载的字节长度(最高 65,535 字节)。
\n
Buffer Overread (越界读取)
程序读取超出预定内存缓冲区边界的内存安全漏洞,导致相邻敏感数据泄露。
\n
无界限 memcpy()
在未根据实际接收记录大小校验的情况下,盲目根据客户端参数执行内存拷贝。

逐步攻击与漏洞执行机制剖析

1

发送恶意心跳请求包

攻击者与 TLS 服务器握手,发送仅含 1 字节有效负载('A')的心跳包,但将长度声明篡改为 65,535 字节(0xFFFF)。

\n
2

缺失负载边界长度校验

OpenSSL 通过 n2s(p, payload) 解析长度,却未检验 1 + 2 + payload + 16 <= rrec.length 是否成立。

\n
3

过度分配 64KB 回复缓冲区

服务器完全依据客户端伪造的声明,在堆中分配整整 64KB 的回复内存空间。

\n
4

越界拷贝导致核心数据外发

memcpy() 越过 1 字节数据包边界,将相邻堆内存中的 RSA 私钥和用户凭据一同复制并通过 TLS 发送回攻击者。

源码对比:tls1_process_heartbeat() 中的边界校验

未修复漏洞:OPENSSL 1.0.1f 缺失边界长度检查
/* 直接从客户端数据包读取 16 位长度,未作边界检查 */
n2s(p, payload);
pl = p;

/* 根据客户端声明的假长度分配回复缓冲区 */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;

/* 致命错误:向后复制长达 64KB 的服务器堆内存! */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
加固补丁:严格校验实际接收记录边界 (RFC 6520)
/* 从数据包中解析 16 位长度 */
n2s(p, payload);
pl = p;

/* 修复:验证声明的载荷长度未超出实际接收到的记录总长 */
if (1 + 2 + payload + 16 > s->s3->rrec.length)
    return 0; /* 静默丢弃格式畸形的心跳数据包 */

buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
memcpy(bp, pl, payload);

工程与系统安全加固清单

← 所有交互式模拟器 阅读 CVE-2014-0160 Heartbleed 完整深度剖析 →