FlawOpen

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

● CVE-2014-0160 · CVSS 7.5 · Tinggi
Riset Keamanan · FlawOpen

CVE-2014-0160: kebocoran memori Heartbleed

CVE-2014-0160 memungkinkan peer TLS atau DTLS membaca hingga 64 KiB melewati record Heartbeat ketika OpenSSL memercayai panjang payload yang tidak ada di dalam record. Perbaikan upstream memvalidasi record sebelum mengurai dan menggemakan payload.[1], [2]

💡 Penjelasan Sederhana (ELI5)

Bayangkan seorang petugas menerima kartu berisi beberapa kata, tetapi percaya pada label yang meminta salinan jauh lebih panjang. Alih-alih berhenti di tepi kartu, ia terus menyalin teks berikutnya dari baki bersama. Heartbleed membuat OpenSSL membaca melewati record yang diterima; byte yang terbuka bergantung pada isi memori proses.[1], [3]

Konsep Kunci & Istilah

Heartbeat TLS/DTLS (RFC 6520)
Pesan keep-alive pada TLS atau DTLS. Permintaan berisi payload yang dikembalikan peer serta padding yang diwajibkan protokol.[3]
payload_length
Field 16-bit yang menyatakan ukuran payload Heartbeat. Payload harus muat di record yang diterima setelah tipe pesan, field panjang, dan padding minimum.[1], [3]
memcpy()
Menyalin jumlah byte tertentu dari pointer sumber. Fungsi ini tidak mengetahui panjang buffer sumber yang valid; pemanggil harus memvalidasinya.[1], [2]
Pembacaan melewati buffer (CWE-126)
Membaca setelah akhir buffer sumber yang semestinya. Pada Heartbleed, balasan dapat mengungkap hingga 64 KiB memori proses, bergantung pada isinya.[5]

Pemetaan kerangka kerja

Analisis Akar Masalah (Root Cause)

tls1_process_heartbeat() dan dtls1_process_heartbeat() membaca panjang payload 16-bit dari pesan Heartbeat lalu meneruskannya ke memcpy() dalam jalur balasan tanpa memastikan byte payload sebanyak itu tersedia di s->s3->rrec.length. Peer dapat menyatakan data lebih banyak daripada yang dibawa record TLS atau DTLS. OpenSSL lalu menggemakan byte setelah record yang diterima dan berpotensi mengungkap hingga 64 KiB memori proses; isinya bergantung pada memori saat itu, sehingga key, kata sandi, atau cookie tertentu tidak dijamin muncul. Commit upstream 96db902 terlebih dahulu menolak record yang terlalu pendek untuk memuat tipe, field panjang, dan padding minimum, lalu membandingkan 1 + 2 + payload + 16 dengan panjang record yang diterima. Perbaikan juga membatasi balasan menggunakan SSL3_RT_MAX_PLAIN_LENGTH dan memakai write_length yang dihitung. Pola pemeriksaan yang sama diterapkan pada handler TLS dan DTLS.[1], [2], [3], [4]

Alur Serangan Langkah demi Langkah

Langkah 1

Peer mengirim record Heartbeat yang pendek

Peer TLS atau DTLS mengirim pesan Heartbeat dengan panjang payload yang dinyatakan lebih besar daripada byte payload yang tersedia di record.[1], [3]

Langkah 2

OpenSSL memercayai panjang yang dinyatakan

Sebelum perbaikan, handler membaca tipe dan panjang tanpa lebih dulu memvalidasi ukuran minimum record atau mencocokkan payload dengan record yang diterima.[1], [2]

Langkah 3

Balasan menyalin melewati record

memcpy() menyalin jumlah byte yang dinyatakan dari buffer record. Balasan dapat mencakup byte setelah pesan Heartbeat yang diterima, hingga batas protokol 64 KiB.[1], [2]

Langkah 4

Paparan bergantung pada isi proses

Peer dapat menerima byte dari memori proses. Balasan tidak menjamin secret tertentu; hasilnya bergantung pada isi memori dan keadaan endpoint.[1], [4]

Langkah 5

Handler yang diperbaiki menolak ketidakcocokan

Perbaikan memeriksa header dan padding sebelum parsing, memastikan payload muat di record yang diterima, lalu membatasi balasan sebelum menyalin.[2], [1]

Kode Sumber: Rentan vs Aman

Cuplikan ini berasal dari perubahan upstream OpenSSL dan bukan program mandiri. Kode rentan mengurai field sebelum memeriksa keberadaan header tetap dan padding minimum, lalu menyalin panjang payload yang dinyatakan peer. Perbaikan memeriksa ukuran minimum record sebelum parsing, mencocokkan payload yang dinyatakan dengan record yang diterima, dan membatasi panjang balasan. OpenSSL menerapkan perubahan terkait pada tls1_process_heartbeat() dan dtls1_process_heartbeat().[2], [1]

Cuplikan sumber: ssl/t1_lib.c

IMPLEMENTASI RENTAN
/* Kutipan tls1_process_heartbeat() sebelum perbaikan. */
hbtype = *p++;
n2s(p, payload);
pl = p;

/* Pada jalur respons TLS1_HB_REQUEST: */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT,
                     buffer, 3 + payload + padding);
PERBAIKAN AMAN & KUAT
/* Tolak record yang terlalu pendek untuk memuat tipe, panjang, dan padding minimum. */
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;

/* Pada jalur respons 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);

Kronologi Insiden

2012-03-14

OpenSSL 1.0.1 dirilis dengan pemrosesan TLS/DTLS Heartbeat yang tidak memeriksa panjang record.[3], [1]

2014-04-07

OpenSSL menerbitkan advisori CVE-2014-0160 dan merilis 1.0.1g; advisori tersebut berterima kasih kepada Neel Mehta dari Google Security. Perbaikan untuk beta 1.0.2 menyusul pada beta2.[1], [2]

2014-04

Operator menambal endpoint terdampak dan menilai kemungkinan paparan. Heartbleed.com menyebut log biasa tidak mencatat byte memori apa yang dikembalikan respons; setelah patch, penggantian key, sertifikat, sesi, dan kredensial perlu dinilai.[6], [1]

Daftar Periksa Penguatan Sistem Rekayasa

Sumber