flawopen.com/Teardowns/cve-2014-0160-heartbleed
Análise técnica linha por linha do patch da CVE-2014-0160 (Heartbleed): a verificação de limites ausente no tls1_process_heartbeat do OpenSSL que expunha 64 KB de memória por requisição.
Imagine enviar uma única palavra de 4 letras 'BIRD' para um papagaio treinado e dizer: 'Repita minha palavra de 4 letras, mas faça sua resposta ter 64.000 letras'. O papagaio grasna 'BIRD' e imediatamente começa a tagarelar as 63.996 letras seguintes armazenadas em sua memória recente — incluindo senhas secretas, chaves privadas e números bancários de outros visitantes. No Heartbleed, o OpenSSL confiava no tamanho declarado da mensagem sem verificar o comprimento real do pacote, copiando a memória do servidor diretamente de volta ao invasor.
Open Source SystemsCWE-SecurityDefense-in-DepthA causa raiz decorre de parâmetros de limite não validados em sistemas de código aberto, permitindo a dessincronização de estado e a evasão dos controles de segurança.
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().:.