
Der Heartbleed-Bug `CVE-2014-0160` ist ein schwerwiegender Implementierungsfehler in der OpenSSL-Bibliothek, der es Angreifern ermöglicht, Daten aus dem Speicher des Opferservers zu stehlen. Der Inhalt der gestohlenen Daten hängt davon ab, was sich im Speicher des Servers befindet. Er kann potenziell private Schlüssel, TLS-Sitzungsschlüssel, Benutzernamen, Passwörter, Kreditkarten usw. enthalten. Die Schwachstelle liegt in der Implementierung des Heartbeat-Protokolls, das von SSL/TLS verwendet wird, um die Verbindung aufrechtzuerhalten.
Der Heartbleed-Bug CVE-2014-0160 ist ein schwerwiegender Implementierungsfehler in der OpenSSL-Bibliothek, der Angreifern ermöglicht, Daten aus dem Speicher des Opfer-Servers zu stehlen. Der Inhalt der gestohlenen Daten hängt davon ab, was sich im Speicher des Servers befindet. Es könnten potenziell private Schlüssel, TLS-Sitzungsschlüssel, Benutzernamen, Passwörter, Kreditkarten usw. enthalten sein. Die Schwachstelle liegt in der Implementierung des Heartbeat-Protokolls, das von SSL/TLS verwendet wird, um die Verbindung aufrechtzuerhalten.
Der betroffene OpenSSL-Versionsbereich reicht von 1.0.1 bis 1.0.1f. Die Version in der Ubuntu-VM ist 1.0.1.
Der Heartbleed-Angriff basiert auf der Heartbeat-Anfrage. Diese Anfrage sendet einfach einige Daten an den Server, und der Server kopiert die Daten in sein Antwortpaket, sodass alle Daten zurückgesendet werden. Im Normalfall nehmen wir an, dass die Anfrage 3 Bytes Daten "ABC" enthält, sodass das Längenfeld den Wert 3 hat. Der Server legt die Daten im Speicher ab und kopiert 3 Bytes vom Anfang der Daten in sein Antwortpaket. Im Angriffsszenario kann die Anfrage 3 Bytes Daten enthalten, aber das Längenfeld kann 1003 angeben. Wenn der Server sein Antwortpaket zusammenstellt, kopiert er vom Anfang der Daten (d.h. "ABC"), aber er kopiert 1003 Bytes anstelle von 3 Bytes. Diese zusätzlichen 1000 Bytes stammen offensichtlich nicht aus dem Anfragepaket; sie stammen aus dem privaten Speicher des Servers und können Informationen anderer Benutzer, geheime Schlüssel, Passwörter usw. enthalten.
Als nächstes ändern Sie das Längenfeld der Anfrage. Lassen Sie uns zunächst verstehen, wie das Heartbeat-Antwortpaket aus der obigen Abbildung aufgebaut wird. Wenn das Heartbeat-Anfragepaket eintrifft, analysiert der Server das Paket, um die Nutzlast und den -Wert zu erhalten (der oben hervorgehoben ist). Hier ist die Nutzlast nur ein 3-Byte-String und der -Wert ist genau 3. Das Serverprogramm übernimmt diesen Längenwert blind aus dem Anfragepaket. Es erstellt dann das Antwortpaket, indem es auf den Speicher zeigt, der speichert, und kopiert Bytes in die Antwortnutzlast. Auf diese Weise würde das Antwortpaket einen 3-Byte-String enthalten.
Payload_length"ABC"Payload_length"ABC"Payload_length"ABC"Als nächstes starten Sie den Heartbleed-Angriff wie in der folgenden Abbildung gezeigt. Behalten Sie dieselbe Nutzlast (3 Bytes) bei, aber setzen Sie das Payload_length-Feld auf 1003. Der Server wird diesen Payload_length-Wert beim Erstellen des Antwortpakets wieder blind übernehmen. Dieses Mal zeigt das Serverprogramm auf den String "ABC" und kopiert 1003 Bytes aus dem Speicher als Nutzlast in das Antwortpaket. Neben dem String "ABC" werden die zusätzlichen 1000 Bytes in das Antwortpaket kopiert, bei denen es sich um alles aus dem Speicher handeln kann, z. B. geheime Aktivitäten, Protokollinformationen, Passwörter usw.
Der Angriffscode ermöglicht es, den Payload_length-Wert zu ändern. Standardmäßig ist der Wert auf einen recht großen Wert (0x4000) gesetzt, aber er kann reduziert werden.
Der einfachste Weg, die Heartbleed-Sicherheitslücke zu beheben, ist die Aktualisierung der OpenSSL-Bibliothek auf die neueste Version. Das Ziel ist es jedoch, die Sicherheitslücke über den Quellcode zu patchen.
Format des Heartbeat-Anfrage-/Antwortpakets
struct {
HeartbeatMessageType type; // 1 byte: request or the response
uint16 payload_length; // 2 byte: the length of the payload
opaque payload[HeartbeatMessage.payload_length];
opaque padding[padding_length];
} HeartbeatMessage;
Das erste Feld (1 Byte) des Pakets enthält die Typinformationen, das zweite Feld (2 Bytes) ist die Nutzlastlänge, gefolgt von der eigentlichen Nutzlast und Padding. Die Größe der Nutzlast sollte dem Wert im Nutzlastlängenfeld entsprechen, aber im Angriffsszenario kann die Nutzlastlänge auf einen anderen Wert gesetzt werden. Das folgende Code-Snippet zeigt, wie der Server die Daten aus dem Anfragepaket in das Antwortpaket kopiert.
Heartbeat-Anfragepaket verarbeiten und Antwortpaket generieren
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
// Read from type field first
hbtype = *p++; /* After this instruction, the pointer
* p will point to the payload_length field */
// Read from the payload_length field from the request packet
n2s(p, payload); /* Function n2s(p, payload) reads 16 bits
* from pointer p and store the value
* in the INT variable "payload". */
pl = p; // pl points to the beginning of the payload content
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;
int r;
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
// Enter response type, length and copy payload *bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
// copy payload
memcpy(bp, pl, payload); /* pl is the pointer which
* points to the beginning
* of the payload content */
bp += payload;
// Random padding
RAND_pseudo_bytes(bp, padding);
// this function will copy the 3+payload+padding bytes
// from the buffer and put them into the heartbeat response
// packet to send back to the request client side.
OPENSSL_free(buffer);
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
}
Die Sicherheitslücke liegt hier
// copy payload
memcpy(bp, pl, payload);
Es gibt keine Überprüfung, ob pl gültig ist oder nicht. Daher kann ein Speicherverstoß auftreten.
Patches:
memcpy()Patches wurden in der VM erstellt, sind aber in diesem Repo nicht sichtbar.
Vielen Dank für Ihr Interesse, dieses Projekt hat Spaß gemacht und war aufschlussreich!