flawopen.com/Teardowns/cve-2014-0160-heartbleed
Analyse technique ligne par ligne du correctif de CVE-2014-0160 (Heartbleed) : le contrôle de limites manquant dans tls1_process_heartbeat d'OpenSSL exposant 64 Ko de mémoire serveur par requête.
Imaginez envoyer un mot de 4 lettres 'BIRD' à un perroquet dressé en lui disant : 'Répète mon mot de 4 lettres, mais fais en sorte que ta réponse contienne 64 000 lettres'. Le perroquet crie 'BIRD' puis se met aussitôt à débiter les 63 996 lettres suivantes de sa mémoire récente — y compris les mots de passe secrets, clés privées et numéros bancaires d'autres visiteurs. Dans Heartbleed, OpenSSL a fait confiance à la longueur annoncée par le client sans vérifier la taille réelle du paquet, renvoyant la mémoire brute du serveur à l'attaquant.
Open Source SystemsCWE-SecurityDefense-in-DepthLa cause fondamentale provient de paramètres de limites non validés dans les systèmes open source, permettant une désynchronisation d'état et le contournement des contrôles de sécurité.
Attacker connects to a TLS server and sends a Heartbeat Request containing a 1-byte payload ('A').
Attacker sets the length field to the maximum possible value: 0xFFFF (65,535 bytes).
The server allocates a 64KB response buffer based on the client's claimed size and calls memcpy().
The memory copy overreads past the end of the packet, dumping private SSL keys, user passwords, and active session tokens.
/* 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);
memcpy().:.