flawopen.com/Teardowns/cve-2014-0160-heartbleed
Análisis línea por línea del parche de CVE-2014-0160 (Heartbleed): la verificación de límites ausente en tls1_process_heartbeat de OpenSSL que exponía 64 KB de memoria del servidor por petición.
Imagine enviar una sola palabra de 4 letras 'BIRD' a un loro entrenado y decirle: 'Repite mi palabra de 4 letras, pero haz que tu respuesta tenga 64.000 letras de largo'. El loro grazna 'BIRD' e inmediatamente comienza a balbucear las siguientes 63.996 letras almacenadas en su memoria reciente, incluidas contraseñas secretas, claves privadas y números bancarios de otros visitantes. En Heartbleed, OpenSSL confió en la longitud declarada por el cliente sin verificar el tamaño real del paquete, copiando la memoria sin procesar del servidor al atacante.
Open Source SystemsCWE-SecurityDefense-in-DepthLa causa raíz se debe a parámetros de límite no validados en sistemas de código abierto, lo que permite la desincronización de estado y la elusión de controles de seguridad.
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().:.