OpenSSL bug – and why you should log off from facebook!! –

Categories: Programming


In this post I’m talking about the bug recently discovered on OpenSSL and why is so important.


SSL (Secure Sockets Layerv2/3) and its replacement, TLS (Transport Layer Security), are cryptography protocol which  provide communication security over the Internet. In a Client-Server communication they provide a “secure” communication through 1) authentication 2) data integrity 3) encryption.In a layered view SSL and TLS are on top of TCP and IP.


OpenSSL is the open source implementation of the SSL and TLS protocols. From the OpenSSL website: “The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) protocols”

WHO does use OpenSSL?

OpenSSL is used by webServers like Apache, applications over the internet (e.g.: mail), and any software need to establish a secure client-server connection. As apache is the web-server most widely used on Internet means that OpenSSL is pretty widespread. For example Amazon on its server use Apache but it has not been affected as doesn’t use the OpenSSL buggy release. So every time you see in the address bar of our browser: means that your browser (client)is using a secure connection with the server (and secure connection means using OpenSSL). But OpenSSL is just one implementation the server might use (another example of SSL/TLS open source implementation is GnuTLS).


OpenSSL 1.0.1 released in December 2011 introduced the “HEARTBLEED” bug! so this bug has been out for more that 2 years. A bit of context:Once a client-server session is established (e.g.: you open your Facebook account), that connection is valid for a “time-out period”. After that period the secure session has to be re-established. In order to avoid this, the  OpenSSL team has implemented an extension (defined in RFC 6520 TLS/DTLS Heartbeat Extension) (and honestly looks like an old fashioned solution, more elegant one is explained here). So, in order to avoid frequent session down/session up the server “ask” “are you still up?” every time needed in order to keep the session established . This request and the relative answer (response) are messages defined in structures into the OpenSSL code. The interaction is roughly like this:

  • SERVER_1: “ask” “are you still up?RANDOM_DATA“: server_1 send a request to server_2 with a request message filled out with the message type(REQUEST in this case), payload length (the length of the payload data sent to the server_2), payload (random data sent to the server_2)and padding (not important for the time being).
  • SERVER_2: answer “yes, I’m RANDOM_DATA” replaying with the RESPONSE message: server_2 will send back the same information received with a couple of modification: the message_type will of RESPONSE. The Payload length the same value received from the server_1. Payload is the same (RANDOM_DATA) received by the server_2.

Below a code snippet from sending REQUEST (from the server_1 to the server_2) (d1_both.cint dtls1_heartbeat(SSL *s) method).

/* Create HeartBeat message, we just use a sequence number
* as payload to distuingish different messages and add
* some random stuff.
* - Message Type, 1 byte
* - Payload Length, 2 bytes (unsigned int)
* - Payload, the sequence number (2 bytes uint)
* - Payload, random bytes (16 bytes uint)
* - Padding
buf = OPENSSL_malloc(1 + 2 + payload + padding);
p = buf;
/* Message Type */
/* Payload length (18 bytes here) */
s2n(payload, p);
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
RAND_pseudo_bytes(p, 16);
p += 16;
/* Random padding */
RAND_pseudo_bytes(p, padding);

ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);

a malicious server could set the payload length to 64KB (remember that the data type of the payload length field is 2 byte, 2^16=64K) but the data (into the Payload buffer) are not 64K of random number but just few byte. The server_2 doesn’t check any boundary or buffer limit once received the data and then just make a memcpy … guess what? the data copied back is a chunk of 64K with (likely) a lot of sensible information! so a (malicious) server could keep sending Heartbeat request to a server collecting a lot of information (password, session id, etc.)

Below a snippet of (buggy) code from the receiving REQUEST (from the server_2) and sending RESPONSE (to the server_1). int dtls1_process_heartbeat(SSL *s) method and d1_both.c module. As you can see there is not boundary check on the received message so what that method does is just composing the response coping the payload data (sending back like a mirror to the server_1) for the payload length indicated. the problem is that the payload length was 64K but there are no 64K data in the payload message 🙁 … what dtls1_process_heartbeat method does is coping data present on the stack in that moment (64K byte data).

int dtls1_process_heartbeat(SSL *s)
unsigned char *p = &s->s3->[0], *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */

/* Read type and payload length first */
hbtype = *p++;
n2s(p, payload);
pl = p;

// OnV: ... some code
// OnV: ... malloc and sending section!

/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;
/* Enter response type, length and copy payload */
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, 3 + payload + padding);

the FIXED code: (I’ve added some comment to explain better. Those comment are not present in the original code but just here for clarity purpose!)

int dtls1_process_heartbeat(SSL *s)
unsigned char *p = &s->s3->[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->[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) // OnV: fix2 (this is THE fix): basically ensuring that
// there are payload length data into the received buffer.
return 0; /* silently discard per RFC 6520 sec. 4 */
pl = p;

So for this reason the word HEARTBLEED directly came from Heartbeat.


This bug was independently discovered by a team of security engineers (Riku, Antti and Matti) at Codenomicon and Neel Mehta of Google Security, who first reported it to the OpenSSL team.


  • OpenSSL 1.0.1 through 1.0.1f (inclusive) are vulnerable
  • OpenSSL 1.0.1g is NOT vulnerable
  • OpenSSL 1.0.0 branch is NOT vulnerable
  • OpenSSL 0.9.8 branch is NOT vulnerable


Server admin:

  • Use the last version (patched) of openSSL.
  • If not possible recompile your code with -DOPENSSL_NO_HEARTBEATS


  • Explicitly log off any time you’re going to close a secure connection: E.g.: I’m sure anytime you open your Facebook account you don’t have to add any user_id or password. This is why the (Facebook) server has a still valid session_id because last time you used fb you didn’t log-off. Now, what if I can stole your session_id (e.g.: through the OpenSSL bug)? that I can get access to your fb account …. now we’re talking about fb … but the same is (potentially) valid for other online service (ecommerce website, back account, etc). So explicitly LOG-OFF any time you don’t need anymore a service in order to INVALIDATE a session on the server.
  • Change your passwords every month or two.



    Leave a Reply

    Your email address will not be published.

    This site uses Akismet to reduce spam. Learn how your comment data is processed.