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

flawopen.com/シミュレーター/Heartbleed バッファ過剰読み取り

メモリ安全性 / OpenSSL TLS

OpenSSL Heartbleed バッファ過剰読み取りインタラクティブシミュレーター (CVE-2014-0160)

ブラウザ上で動作するメモリモデルとパケット検証シミュレーター。未検証の TLS Heartbeat 長さフィールドがサーバーヒープの過剰読み取りを引き起こす仕組みをステップ実行。

💡 わかりやすい解説 (ELI5)

訓練されたオウムに4文字の単語「BIRD」を伝え、「この単語を繰り返して。ただし回答は64,000文字にしてね」と指示したと想像してください。オウムは「BIRD」と鳴いた後、直近の記憶に残っている次の63,996文字(他の訪問者が話した秘密のパスワードや暗号鍵、口座情報など)を一気に喋り出します。Heartbleed では、OpenSSL がパケットの実際の長さを検証せずにクライアントの自己申告した長さを盲信し、サーバーの生メモリを攻撃者にそのままコピーして返してしまいました。

主要概念とサブシステム用語

TLS Heartbeat 拡張
RFC 6520 で定義された、再ネゴシエーションなしで通信路を維持するキープアライブ機構。
\n
Payload Length フィールド
ハートビートヘッダー内の16ビット符号なし整数で、受信ペイロードのバイト長を宣言(最大65,535バイト)。
\n
Buffer Overread
プログラムが意図された境界を超えて隣接するメモリ領域まで読み取ってしまう脆弱性。
\n
境界未検査 memcpy()
受信パケットの実サイズを確認せず、クライアントの申告値に基づいて実行されるメモリコピー。

ステップ別の攻撃及び実行メカニズム

1

不正な Heartbeat リクエストの送信

攻撃者は1バイト('A')のみを送信しつつ、長さフィールドを65,535バイト(0xFFFF)と偽装したパケットを送信。

\n
2

パケット長チェックの欠落

OpenSSL は n2s(p, payload) で長さを取得するが、1 + 2 + payload + 16 <= rrec.length の確認を怠る。

\n
3

64KB レスポンスバッファの過大確保

サーバーは申告値を盲信してヒープ上に64KBのバッファを確保し、応答ヘッダーを構築。

\n
4

ヒープメモリの過剰読み取りと漏洩

memcpy() がパケット末尾を超えて隣接メモリを走査し、SSL 秘密鍵やセッショントークンを攻撃者に送出。

ソースコード比較: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 詳細解説を読む →