flawopen.com/Teardowns/cve-2014-0160-heartbleed

● CVE-2014-0160 · CVSS 9.8 · 严重
安全研究 · FlawOpen

深度技术拆解:CVE-2014-0160: OpenSSL Heartbleed Buffer Overread

CVE-2014-0160(心脏出血 / Heartbleed)源码级补丁深度剖析:解析 OpenSSL 的 tls1_process_heartbeat 中因缺失边界检查导致单次请求泄露 64KB 核心服务器内存的完整技术机理。

💡 通俗易懂的原理解析 (ELI5)

想象一下,你给一只训练有素的鹦鹉发送了一个 4 个字母的单词 'BIRD',并对它说:'重复我这 4 个字母的单词,但你的回答必须有 64,000 个字母长'。鹦鹉尖叫了一声 'BIRD',紧接着开始喋喋不休地背诵它脑海中储存的后续 63,996 个字符——其中赫然包含其他访客刚说过的绝密密码、私钥和银行账号。在 Heartbleed(心脏出血)漏洞中,OpenSSL 盲目相信了客户端声称的消息长度,却未校验数据包的真实尺寸,将服务器内存中的敏感明文直接倾倒给了攻击者。

核心概念与专有名词

Open Source Systems
技术概念 (Open Source Systems):Core architecture component affected by CWE-Security.
CWE-Security
技术概念 (CWE-Security):Standard Common Weakness Enumeration classification for cve-2014-0160-heartbleed.
Defense-in-Depth
技术概念 (Defense-in-Depth):Multi-layered engineering verification and runtime boundary isolation.

根本原因剖析 (Root Cause)

根本原因在于开源系统中未经验证的边界参数,导致状态不同步并绕过安全控制。

攻击执行流程分解

Step 1

Malformed Heartbeat Request

Attacker connects to a TLS server and sends a Heartbeat Request containing a 1-byte payload ('A').

Step 2

Length Header Manipulation

Attacker sets the length field to the maximum possible value: 0xFFFF (65,535 bytes).

Step 3

Unbounded Heap Buffer Allocation

The server allocates a 64KB response buffer based on the client's claimed size and calls memcpy().

Step 4

Adjacent Memory Exfiltration

The memory copy overreads past the end of the packet, dumping private SSL keys, user passwords, and active session tokens.

源代码对比:漏洞与安全实现

✕ 存在漏洞的实现
/* Read 16-bit length directly from client packet without bounds check */
n2s(p, payload);
pl = p;

/* Allocate reply buffer based on client's claimed size */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;

/* BUG: Copies up to 64KB of adjacent server heap memory! */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
✓ 加固后的安全修复
/* Read 16-bit length from packet */
n2s(p, payload);
pl = p;

/* FIX: Validate that claimed payload does not exceed actual received record length */
if (1 + 2 + payload + 16 > s->s3->rrec.length)
    return 0; /* Silently discard malformed heartbeat */

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

工程与系统安全加固清单