flawopen.com/Teardowns/cve-2014-0160-heartbleed
CVE-2014-0160:OpenSSL Heartbleed 内存泄露
CVE-2014-0160 使 TLS 或 DTLS 对端在 OpenSSL 信任记录中不存在的载荷长度时,可以读取 Heartbeat 记录之外最多 64 KiB 的数据。上游修复会先验证记录,再解析并回显载荷。[1], [2]
想象一名工作人员收到一张只有几个字的卡片,却相信标签上要求复制很长一段文字。他没有在卡片边缘停下,而是继续抄写共享托盘里后面的内容。Heartbleed 让 OpenSSL 读取到已接收记录之外;泄露哪些字节取决于进程内存中的实际内容。[1], [3]
核心概念与专有名词
TLS/DTLS Heartbeat(RFC 6520)- TLS 或 DTLS 的保活消息。请求携带一个由对端回显的载荷,以及协议要求的填充。[3]
缓冲区越界读取(CWE-126)- 读取预期源缓冲区末尾之后的数据。Heartbleed 的响应可能泄露最多 64 KiB 进程内存,具体取决于内存内容。[5]
框架映射
- 本指南所述弱点的 CWE 参考: CWE-126
- CISA KEV — 收录日期 2022-05-04 — CVE-2014-0160
根本原因剖析 (Root Cause)
tls1_process_heartbeat() 和 dtls1_process_heartbeat() 会读取 Heartbeat 消息的 16 位载荷长度,并在响应路径中将其传给 memcpy(),却没有确认 s->s3->rrec.length 中确实包含那么多载荷字节。对端可以声明的长度超过 TLS 或 DTLS 记录实际携带的数据。随后 OpenSSL 会回显已接收记录之后的字节,最多可能泄露 64 KiB 进程内存;内容取决于当时的内存,因此并不保证出现某个特定密钥、密码或 cookie。上游提交 96db902 先丢弃短到无法容纳类型、长度字段和最小填充的记录,再将 1 + 2 + payload + 16 与已接收记录长度比较。它还用 SSL3_RT_MAX_PLAIN_LENGTH 限制响应,并使用计算出的 write_length。TLS 和 DTLS 处理函数都采用了相应检查。[1], [2], [3], [4]
攻击执行流程分解
源代码对比:漏洞与安全实现
这些代码片段来自 OpenSSL 上游修复,并非独立可运行程序。漏洞代码在确认固定头部和最小填充存在之前就解析字段,随后按对端声明的载荷长度复制。修复先检查记录的最小长度,再将声明的载荷与已接收记录核对,并限制响应长度。OpenSSL 对 tls1_process_heartbeat() 和 dtls1_process_heartbeat() 都作了对应修改。[2], [1]
源码摘录: ssl/t1_lib.c
/* tls1_process_heartbeat() 修复前的代码片段。 */
hbtype = *p++;
n2s(p, payload);
pl = p;
/* 在 TLS1_HB_REQUEST 响应路径中: */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT,
buffer, 3 + payload + padding);
/* 如果记录长度不足以容纳类型、长度字段和最小填充,则拒绝该记录。 */
if (1 + 2 + 16 > s->s3->rrec.length)
return 0;
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length)
return 0;
pl = p;
/* 在 TLS1_HB_REQUEST 响应路径中: */
unsigned int write_length = 1 + 2 + payload + padding;
if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
buffer = OPENSSL_malloc(write_length);
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
事件演进时间线
工程与系统安全加固清单
- ✓升级到包含修复且仍受供应商支持的 OpenSSL 版本;上游修复版本为 1.0.1g 和 1.0.2-beta2。应核实发行版回移补丁,而不只看显示的版本号。[1], [2]
- ✓对可能暴露的端点,更换受影响的 TLS 私钥和证书;若存在合理的泄露可能,应吊销旧证书。也要纳入处理过不可信 Heartbeat 的客户端。[6]
- ✓修补易受攻击的服务后,轮换可能存在于其进程内存中的凭据。只有在服务负责人确认修复完成后,才更改用户密码。[6], [8]
- ✓针对记录边界测试 TLS 和 DTLS 处理函数:固定头部过短、载荷长度大于已接收字节,以及带最小填充的有效请求。[2], [3]
- ✓若不需要 Heartbeat 且兼容性允许,可使用
-DOPENSSL_NO_HEARTBEATS重新编译;这是 OpenSSL 公告列出的替代缓解措施。[1]
参考来源
- OpenSSL Security Advisory — TLS heartbeat read overrun (CVE-2014-0160)
- OpenSSL upstream fix — commit 96db902
- RFC 6520 — TLS and DTLS Heartbeat Extension
- NVD — CVE-2014-0160
- MITRE CWE-126 — Buffer Over-read
- Codenomicon / Heartbleed.com — The Heartbleed Bug
- CVE Program — CVE-2014-0160
- CISA — “Heartbleed” OpenSSL Vulnerability