flawopen.com/Teardowns/CVE-2014-0160 Heartbleed

CVE-2014-0160: OpenSSL Heartbleed Buffer Overread

Critical 9.8 CWE-126 Patch Teardown
ELI5 — The Parrot Memory Spill

Imagine sending a single 4-letter word 'BIRD' to a trained parrot and saying: 'Repeat back my 4-letter word, but make your answer 64,000 letters long.' The parrot squawks 'BIRD' and then immediately starts babbling the next 63,996 letters stored in its recent memory—including the secret passwords, private keys, and bank numbers spoken by other visitors. In Heartbleed, OpenSSL trusted the client's claimed message length without checking how long the packet actually was, copying raw server memory straight back to the attacker.

Target: OpenSSL TLS heartbeat extension (RFC 6520)
Vector: Sending 1-byte payload with an inflated 65,535-byte length field
Impact: Server private keys, session cookies, and plaintext passwords leaked
Remediation: Strict boundary validation before buffer allocation and memcpy

The Mechanism & Root Cause

In ssl/t1_lib.c and ssl/d1_both.c, OpenSSL read a 16-bit integer payload length (n2s(p, payload)) directly from the incoming heartbeat packet. It then allocated a response buffer and copied payload bytes into the reply using memcpy() without checking whether the packet actually contained that many bytes.

ssl/t1_lib.c (Vulnerable OpenSSL 1.0.1f)Vulnerable
/* 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);
ssl/t1_lib.c (Patched OpenSSL 1.0.1g)Hardened
/* 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);

The Attack & Exploit Sequence

Defensive Engineering & Prevention Rules

Explore related security topics and post-mortems: Complete Security Directory →