flawopen.com/Teardowns/cve-2014-0160-heartbleed
Построчный технический разбор патча CVE-2014-0160 (Heartbleed): пропущенная проверка границ в tls1_process_heartbeat OpenSSL, раскрывавшая 64 КБ памяти сервера на каждый запрос.
Представьте, что вы отправляете дрессированному попугаю слово из 4 букв 'BIRD' и говорите: 'Повтори мое слово, но сделай ответ длиной 64 000 букв'. Попугай выкрикивает 'BIRD' и сразу же начинает выпаливать следующие 63 996 букв из своей недавней памяти — включая секретные пароли, приватные ключи и банковские реквизиты других посетителей. В уязвимости Heartbleed библиотека OpenSSL поверила заявленной клиентом длине сообщения, не проверив реальный размер пакета, и отправила сырую память сервера прямо злоумышленнику.
Open Source SystemsCWE-SecurityDefense-in-DepthОсновная причина заключается в невалидированных граничных параметрах в системах с открытым исходным кодом, что приводит к рассинхронизации состояний и обходу средств безопасности.
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().:.