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)

訓練されたオウムに「BIRD」という4文字の単語を送り、「この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.

ソースコード比較:脆弱 vs 堅牢化

✕ 脆弱な実装
/* 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);

エンジニアリング&システム堅牢化チェックリスト