A. Summary
[Affected] OpenSSL 1.0.1 through 1.0.1f, OpenSSL 1.0.2-beta
[Overview] A vulnerability in OpenSSL could allow a remote adversary to expose sensitive data, up to 64K chunk in memory
[Impact] High
B. CVE/PoC Code
CVE-2014-0160
US CERT ALERTS
OpenSSL TLS Heartbeat Extension – Memory Disclosure
C. News and Articles
Millions of Android Devices Vulnerable to Heartbleed Bug
Heartbleed developer explains OpenSSL mistake that put Web at risk
xkcd
D. Impact
The Heartbleed Hit List: The Passwords You Need to Change Right Now
The heartbleed-masstest results for TOP 1000 sites
E. How it works
Diagnosis of the OpenSSL Heartbleed Bug
How Heartbleed Works: The Code Behind the Internet’s Security Nightmare
F. Fixed/Update
Adding heartbeat extension bounds check
The following is the fixed part to check the validation from line 17-19 before memcpy(bp, pl, payload). (http://git.openssl.org/gitweb/?p=openssl.git;a=blob_plain;f=ssl/d1_both.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
int dtls1_process_heartbeat(SSL *s) { unsigned char *p = &s->s3->rrec.data[0], *pl; unsigned short hbtype; unsigned int payload; unsigned int padding = 16; /* Use minimum padding */ if (s->msg_callback) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, &s->s3->rrec.data[0], s->s3->rrec.length, s, s->msg_callback_arg); /* Read type and payload length first */ if (1 + 2 + 16 > s->s3->rrec.length) return 0; /* silently discard */ hbtype = *p++; n2s(p, payload); if (1 + 2 + payload + 16 > s->s3->rrec.length) return 0; /* silently discard per RFC 6520 sec. 4 */ pl = p; if (hbtype == TLS1_HB_REQUEST) { unsigned char *buffer, *bp; unsigned int write_length = 1 /* heartbeat type */ + 2 /* heartbeat length */ + payload + padding; int r; if (write_length > SSL3_RT_MAX_PLAIN_LENGTH) return 0; /* Allocate memory for the response, size is 1 byte * message type, plus 2 bytes payload length, plus * payload, plus padding */ buffer = OPENSSL_malloc(write_length); bp = buffer; /* Enter response type, length and copy payload */ *bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload); bp += payload; /* Random padding */ RAND_pseudo_bytes(bp, padding); r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); if (r >= 0 && s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, buffer, write_length, s, s->msg_callback_arg); OPENSSL_free(buffer); if (r < 0) return r; } else if (hbtype == TLS1_HB_RESPONSE) { unsigned int seq; /* We only send sequence numbers (2 bytes unsigned int), * and 16 random bytes, so we just try to read the * sequence number */ n2s(pl, seq); if (payload == 18 && seq == s->tlsext_hb_seq) { dtls1_stop_timer(s); s->tlsext_hb_seq++; s->tlsext_hb_pending = 0; } } return 0; } |