flawopen.com/Teardowns/cve-2014-0160-heartbleed
CVE-2014-0160: Heartbleed-Speicherleck in OpenSSL
CVE-2014-0160 ermöglichte einem TLS- oder DTLS-Peer, bis zu 64 KiB hinter einem Heartbeat-Record zu lesen, wenn OpenSSL einer Payload-Länge vertraute, die der Record nicht enthielt. Der Upstream-Fix prüft den Record, bevor er die Payload auswertet und zurücksendet.[1], [2]
Stellen Sie sich eine Person vor, die eine Karte mit wenigen Wörtern erhält, aber einem Etikett glaubt, das eine viel längere Kopie verlangt. Statt am Kartenrand anzuhalten, kopiert sie weiter den Text, der in der gemeinsamen Ablage folgt. Heartbleed ließ OpenSSL über den empfangenen Record hinaus kopieren; welche Bytes sichtbar wurden, hing vom Prozessspeicher ab.[1], [3]
Kernkonzepte & Begriffe
TLS/DTLS-Heartbeat (RFC 6520)- Keep-alive-Nachricht in TLS oder DTLS. Eine Anfrage enthält eine Payload, die der Peer zurückspiegelt, sowie das vorgeschriebene Padding.[3]
payload_length- 16-Bit-Feld für die Größe der Heartbeat-Payload. Sie muss nach Nachrichtentyp, Längenfeld und Mindest-Padding in den empfangenen Record passen.[1], [3]
memcpy()- Kopiert eine angegebene Bytezahl ab einem Quellzeiger. Die Funktion kennt die gültige Länge des Quellpuffers nicht; der Aufrufer muss sie prüfen.[1], [2]
Pufferüberlesen (CWE-126)- Lesen hinter dem Ende des vorgesehenen Quellpuffers. Bei Heartbleed konnte die Antwort je nach Speicherinhalt bis zu 64 KiB Prozessspeicher offenlegen.[5]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-126
- CISA KEV — aufgenommen am 2022-05-04 — CVE-2014-0160
Ursachenanalyse
tls1_process_heartbeat() und dtls1_process_heartbeat() lasen die 16-Bit-Payload-Länge einer Heartbeat-Nachricht und übergaben sie im Antwortpfad an memcpy(), ohne nachzuweisen, dass diese Payload-Bytes in s->s3->rrec.length vorhanden waren. Ein Peer konnte mehr Daten angeben, als der TLS- oder DTLS-Record enthielt. OpenSSL spiegelte dann Bytes hinter dem empfangenen Record zurück und konnte bis zu 64 KiB Prozessspeicher offenlegen; der Inhalt hing vom Speicher ab, daher war ein bestimmter Schlüssel, ein Passwort oder Cookie nicht garantiert. Der Upstream-Commit 96db902 verwirft zuerst Records, die für Typ, Längenfeld und Mindest-Padding zu kurz sind, und vergleicht anschließend 1 + 2 + payload + 16 mit der Länge des empfangenen Records. Außerdem begrenzt er die Antwort mit SSL3_RT_MAX_PLAIN_LENGTH und verwendet das berechnete write_length. Dasselbe Prüfmuster wurde auf TLS- und DTLS-Handler angewandt.[1], [2], [3], [4]
Schritt-für-Schritt Angriffsablauf
Quellcode: Verwundbar vs. Sicher
Diese Ausschnitte stammen aus der OpenSSL-Upstream-Änderung und sind kein eigenständiges Programm. Der verwundbare Code verarbeitet die Felder, bevor er prüft, ob der feste Header und das Mindest-Padding vorhanden sind, und kopiert danach die vom Peer angegebene Payload-Länge. Der Fix prüft die Mindestgröße des Records vor dem Parsen, validiert die angegebene Payload gegen den empfangenen Record und begrenzt die Antwort. OpenSSL nahm entsprechende Änderungen an tls1_process_heartbeat() und dtls1_process_heartbeat() vor.[2], [1]
Quelltextauszug: ssl/t1_lib.c
/* Auszug aus tls1_process_heartbeat() vor der Korrektur. */
hbtype = *p++;
n2s(p, payload);
pl = p;
/* Im Antwortpfad für TLS1_HB_REQUEST: */
memcpy(bp, pl, payload);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT,
buffer, 3 + payload + padding);
/* Weist einen Datensatz zurück, der für Typ, Länge und Mindestauffüllung zu kurz ist. */
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;
/* Im Antwortpfad für 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);
Vorfall-Zeitstrahl
Betreiber patchen betroffene Endpunkte und bewerten eine mögliche Offenlegung. Heartbleed.com weist darauf hin, dass gewöhnliche Protokolle nicht festhalten, welche Speicherbytes eine Antwort zurückgab; nach dem Patch wird der Austausch von Schlüsseln, Zertifikaten, Sitzungen und Zugangsdaten geprüft.[6], [1]
Checkliste für Engineering & Systemsicherheit
- ✓Aktualisieren Sie auf eine vom Anbieter unterstützte OpenSSL-Version mit dem Fix; upstream wurden 1.0.1g und 1.0.2-beta2 korrigiert. Prüfen Sie Distributions-Backports statt sich nur auf die angezeigte Versionsnummer zu verlassen.[1], [2]
- ✓Ersetzen Sie bei möglicherweise exponierten Endpunkten betroffene TLS-Privatschlüssel und Zertifikate und widerrufen Sie alte Zertifikate, wenn eine Offenlegung plausibel ist; berücksichtigen Sie auch Clients, die nicht vertrauenswürdige Heartbeats verarbeitet haben.[6]
- ✓Erneuern Sie nach der Behebung des anfälligen Dienstes Zugangsdaten, die plausibel im Prozessspeicher vorhanden gewesen sein könnten. Ändern Sie Benutzerpasswörter erst, wenn der Betreiber bestätigt, dass der Dienst behoben ist.[6], [8]
- ✓Testen Sie TLS- und DTLS-Handler an Record-Grenzen: zu kurze feste Header, Payload-Längen über den empfangenen Bytes und gültige Anfragen mit Mindest-Padding.[2], [3]
- ✓Falls Heartbeat unnötig ist und die Kompatibilität es zulässt, kompilieren Sie mit
-DOPENSSL_NO_HEARTBEATSneu, der alternativen Maßnahme aus dem OpenSSL-Hinweis.[1]
Quellen
- OpenSSL Security Advisory — TLS heartbeat read overrun (CVE-2014-0160)
- OpenSSL upstream fix — commit 96db902
- RFC 6520 — TLS and DTLS Heartbeat Extension
- NVD — CVE-2014-0160
- MITRE CWE-126 — Buffer Over-read
- Codenomicon / Heartbleed.com — The Heartbleed Bug
- CVE Program — CVE-2014-0160
- CISA — “Heartbleed” OpenSSL Vulnerability