Who to blame for the heartbleed bug?

A bug in one of the most used SSL implementations showcases the dark side of open-source software.

Last week the Codenomicon group revealed a bug in the heartbeat implementation of the probably most used SSL library - OpenSSL. There are a lot of direct consequences:

  • As most data nowadays is transfered over the web, security relies on HTTPS
  • HTTPS heavily relies on SSL, which means that every secure transaction uses SSL
  • It has therefore been trivial for attackers to grab sensitive data using this bug

At the moment it is not known how many people did know about this bug. It is only known that for instance the NSA did use this exploit to circumvent encryptions. What is known instead, is the name of the person who implemented the heartbeat procedure.

As with all open-source software, the repository is public and also accessible via a nice web interface. OpenSSL used git as VCS and the simplistic gitweb for providing a web interface. We can therefore see the changes, the person who committed the changes and the name of the reviewer.

It did not take too long until the bashing of the person who committed the code started. In my opinion this is all wrong. There are several reasons:

  • Errors are happening - they are not constraint to open-source software
  • In contrast to some public conjectures I doubt that the bug was inserted intentionally
  • What about the reviewer? It was his job to prevent such bugs

But the biggest reason to stop this bashing is the following: Instead of blaming an individual for writing this code, companies and persons who used this code blindly should be bashed. In this case Google, Facebook, Yahoo, ... - you name it. They are all using Linux and open-source software blindly. This is a huge mistake! You cannot just use software that you are not paying for, where everything is open to the world, and consider it safe, robust and bug-free. You have to check yourself - especially when the software you are using is security critical.

My own site(s) have been all secured - why? Because I am using proprietary software with a Windows Server. Windows might have a bad reputation on the client market, but most of it comes from unexperienced users that run their machines with administrator privileges. The same would happen to Linux. Another part of the story is of course the massive market share. However, on the server market it looks completely different. Here it makes much more sense to find exploits for Linux based systems / software. As most of those programs are open-source, finding exploits is easier than with proprietary software (you don't have to guess alone - you can have a look at the code to understand it better). Of course this is sometimes an argument in favor of open-source, but the Heartbleed bug shows that it the on finding a bug, is not always the one who wants to fix the bug.

Dear users, I strongly recommend that instead of blaming a person who write this part of the code, you all should blame the companies that blindly used this software. Those are big companies and they are running big businesses on top of this software. If they trust it blindly, then they either don't care about their users, or they are just fools.

A final note on the bug itself. Taking a short look at the code in t1_lib.c (pretty easy to find in the right commit), revealed two interesting methods:

  • tls1_process_heartbeat()
  • tls1_heartbeat()

The latter sends the heartbeat, the former processes the response. Therefore we need to have a closer look at the code:

unsigned char *p = &s->s3->rrec.data[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;
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);
}
/* ... */

Now the code does not look too bad at this point. Obviously the received data contains a message, which is read. So the type is read from the first character and the character pointer is incremented. No problem so far. Then the function n2s() is called. Actually n2s is a macro that copies two bytes from p to payload. This is the length indicated by the SSL client for the heartbeat payload.

Now it gets tricky. Without checking if an overflow might occur, the pointer p1 is set to same address as p. This missing bounds check can now be used to reveal up to 64k of memory to a connected client or server. Even though this is a trivial mistake (that is probably the most used vulnerability in C programs in general), it is certainly one that may be forgotten too easily. Hence I do not consider it an intentional bug.

Why only 64k memory? OpenSSL allocates as much memory as the client asked for (with two bytes length up to 216 Bytes). The rest is 1 Byte for the heartbeat type, 2 bytes for the payload length, and 16 bytes to pad the response:

buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;

Finally using the size supplied by the attacker rather than its actual length, it copies the request payload bytes to the response buffer.

*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);

If the specified heartbeat request length is larger than its actual length, this memcpy() will read memory past the request buffer and store it in the response buffer which is sent to the attacker.

Preventing this bug is as easy as adding the following statement before the assignment of p1:

// 19 = 1 + 2 + 16 (type, length, padding)
if (payload + 19 > s->s3->rrec.length) 
    return 0;

Unfortunately it is much easier to blame individuals rather than companies. Personally, I wish that publication such bugs will be handled differently in the future, but I highly doubt it.

Created .

References

Sharing is caring!