What is Heartbleed? A coding error that caused a security crisis
- 13 September, 2017 19:53
Heartbleed is a vulnerability that came to light in April of 2014; it allowed attackers unprecedented access to sensitive information, and it was present on thousands of web servers, including those running major sites like Yahoo.
Heartbleed was caused by a flaw in OpenSSL, an open source code library that implemented the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. In short, a malicious user could easily trick a vulnerable web server into sending sensitive information, including usernames and passwords.
The TLS/SSL standards are crucial for modern web encryption, and while the flaw was in the OpenSSL implementation rather than the standards themselves, OpenSSL is so widely used — when the bug was made public, it affected 17% of all SSL servers — that it precipitated a security crisis.
How Heartbleed works
To understand how the Heartbleed vulnerability (CVE-2014-0160) works, you need to know a little bit about how the TLS/SSL protocols operate, and how computers store information in memory.
One important part of the TLS/SSL protocols is what's called a heartbeat. Essentially, this is how the two computers communicating with one another let each other know that they're still connected even if the user isn't downloading or uploading anything at the moment. Occasionally, one of the computers will send an encrypted piece of data, called a heartbeat request, to the other. The second computer will reply back with the exact same encrypted piece of data, proving that the connection is still in place. Crucially, the heartbeat request includes information about its own length.
So, for example, if you're reading your Yahoo mail but haven't done anything in a while to load more information, your web browser might send a signal to Yahoo's servers saying, in essence, "This is a 40 KB message you're about to get. Repeat it all back to me." (The requests can be up to 64 KB long.) When Yahoo's servers receive that message, they allocate a memory buffer — a region of physical memory where it can store information — that's 40 KB long, based on the reported length of the heartbeat request. Next, it stores the encrypted data from the request into that memory buffer, then reads the data back out of it and sends it back to your web browser.
That's how it's supposed to work. The Heartbleed vulnerability arose because OpenSSL's implementation of the heartbeat functionality was missing a crucial safeguard: the computer that received the heartbeat request never checked to make sure the request was actually as long as it claimed to be. So if a request said it was 40 KB long but was actually only 20 KB, the receiving computer would set aside 40 KB of memory buffer, then store the 20 KB it actually received, then send back that 20 KB plus whatever happened to be in the next 20 KB of memory. That extra 20 KB of data is information that the attacker has now extracted from the web server.
This is the crucial part of the operation. Even when a computer is done with information, it persists in memory buffers until something else comes along to overwrite it. If you're the attacker, you have no way to know in advance what might be lurking in that 20 KB you just grabbed off the server, but there are a number of possibilities. It could be gibberish or useless cruft. You could get SSL private keys, which would allow for the decryption of secure communication to that server (this is unlikely, but would be the holy grail for an attacker). More commonly, you could get back usernames and passwords that had been submitted to applications and services running on the server, which would allow you to log in and gain access.
Randall Munroe's web comic xkcd is known for making difficult scientific concepts accessible, especially in computer science, Munroe's specialty. This comic from 2014 does a great job of summarizing how the Heartbleed vulnerability works in a concise way.
Heartbleed bug code
The coding mistake that caused Heartbleed can be traced to a single line of code:
memcpy(bp, pl, payload);
memcpy() is the command that copies data.
bp is the place it's copying it to,
pl is where it's being copied from, and
payload is the length of the data being copied. The problem is that there's never any attempt to check if the amount of data in
pl is equal to the value given of
The most ironic thing here is that OpenSSL is open source software. Anyone could look at the code, and presumably hundreds did, but nobody noticed the fairly elementary coding error.
It's not clear if any real-world exploitation of the Heartbeat vulnerability took place before it was widely publicized. It's possible that some attempted attacks detected by security companies as early as 2013 were probing for the vulnerability — and some think the attackers were government security agencies.
After April of 2014, when the vulnerability was made public, companies scrambled to update their systems, but hackers were able to exploit it in several cases. An attack on Community Health Systems that stole patient data was blamed on Heartbleed, as was the theft of hundreds of social ID numbers from the Canadian Revenue Agency.
How to fix the heartbleed vulnerability
Patches were rolled out for OpenSSL right away when the vulnerability was announced, and in all likelihood most formerly vulnerable servers have been updated by this point, but it can't hurt to test if you're not sure — it's always possible that some server that's important to you has been chugging along for years without a proper upgrade. Pentest-tools.com has a free web-based test that lets you input a URL to discover if a server has been properly patched.
The way to fix the Heartbleed vulnerability is to upgrade to the latest version of OpenSSL. You can find links to all the latest code on the OpenSSL website.
If you're curious about the code that implements the fix, you can look at it — after all, OpenSSL is open source:
* Read type and payload length first */
if (1 + 2 + 16 > s->s3->relent)
/* silently discard */
hbtype = *p++;
if (1 + 2 + payload + 16 > s->s3->rrec.length)
/* silently discard per RFC 6520 sec. 4 */
pl = p;
The first part of this code makes sure that the heartbeat request isn't 0 KB, which can cause problems. The second part makes sure the request is actually as long as it says it is.
If you discover that a server under your control has been left vulnerable for some time, there's more to do than just update the OpenSSL code. For instance, you should change the SSL certificates used by the servers, since they may have been compromised without leaving a trace. More pedestrian but still important: users who have accounts on the system should change their passwords.
Read more about Heartbleed: