Feeds

Anatomy of OpenSSL's Heartbleed: Just four bytes trigger horror bug

The code behind the C-bomb dropped on the world

Beginner's guide to SSL certificates

Analysis The password-leaking OpenSSL bug dubbed Heartbleed is so bad, switching off the internet for a while sounds like a good plan.

A tiny flaw in the widely used encryption library allows anyone to trivially and secretly dip into vulnerable systems, from your bank's HTTPS server to your private VPN, to steal passwords, login cookies, private crypto-keys and much more.

How, in 2014, is this possible?

A simple script for the exploit engine Metasploit can, in a matter of seconds, extract sensitive in-memory data from systems that rely on OpenSSL 1.0.1 to 1.0.1f for TLS encryption. The bug affects about 500,000, or 17.5 per cent, of trusted HTTPS websites, we're told, as well as client software, email servers, chat services, and anything else using the aforementioned versions of OpenSSL.

A good number of popular web services have now been patched following disclosure of the vulnerability on Monday; you can use this tool to check (use at your own risk, of course), but don't forget to do more than patch your OpenSSL installation if you're affected – change your keys, dump your session cookies and evaluate your at-risk data.

Too long, didn't read: A summary

This serious flaw (CVE-2014-0160) is a missing bounds check before a memcpy() call that uses non-sanitized user input as the length parameter. An attacker can trick OpenSSL into allocating a 64KB buffer, copy more bytes than is necessary into the buffer, send that buffer back, and thus leak the contents of the victim's memory, 64KB at a time. The patch is here, and the blunder is far worse than Apple's gotofail.

The TLS heartbeat

The bug lies in OpenSSL's implementation of the TLS heartbeat extension: it's a keep-alive feature in which one end of the connection sends a payload of arbitrary data to the other end, which sends back an exact copy of that data to prove everything's OK. The heartbeat message, according to the official standard, looks like this, in C:

struct
{
  HeartbeatMessageType type;
  uint16 payload_length;
  opaque payload[HeartbeatMessage.payload_length];
  opaque padding[padding_length]; 
} HeartbeatMessage;

This HeartbeatMessage arrives via an SSL3_RECORD structure, a basic building block of SSL/TLS communications. The key fields in SSL3_RECORD are given below; length is how many bytes are in the received HeartbeatMessage and data is a pointer to that HeartbeatMessage.

struct ssl3_record_st
{
  unsigned int length;    /* How many bytes available */
  [...]
  unsigned char *data;    /* pointer to the record data */
  [...]
} SSL3_RECORD;

So just to be clear, the SSL3 record's data points to the start of the received HeartbeatMessage and length is the number of bytes in the received HeartbeatMessage. Meanwhile, inside the received HeartbeatMessage, payload_length is the number of bytes in the arbitrary payload that has to be sent back.

Whoever sends a HeartbeatMessage controls the payload_length but as we will see, this is never checked against the parent SSL3_RECORD's length field, allowing an attacker to overrun memory.

The diagram below shows how the attack works:

The Register illustration of the attack

Click to enlarge ... note: this does not include the padding bytes

In the above example, an attacker sends a four-byte HeartbeatMessage including a single byte payload, which is correctly acknowledged by the SSL3's length record. But the attacker lies in the payload_length field to claim the payload is 65535 bytes in size. The victim ignores the SSL3 record, and reads 65535 bytes from its own memory, starting from the received HeartbeatMessage payload, and copies it into a suitably sized buffer to send back to the attacker. It thus hoovers up far too many bytes, dangerously leaking information as indicated above in red.

Show me the code

The broken OpenSSL code that processes the incoming HeartbeatMessage looks like this, where p is a pointer to the start of the message:

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

So the message type is popped into the hbtype variable, the pointer is incremented by one byte, and the n2s() macro writes the 16-bit length of the heartbeat payload to the variable payload and increments the pointer by two bytes. Then pl becomes a pointer to the contents of the payload.

Let's say a heartbeat message with a payload_length of 65535, ie: a heartbeat with a 64KB payload, the maximum possible, is received. The code has to send back a copy of the incoming HeartbeatMessage, so it allocates a buffer big enough to hold the 64KB payload plus one byte to store the message type, two bytes to store the payload length, and some padding bytes, as per the above structure.

It constructs the reply HeartbeatMessage structure with the following code, where bp is a pointer to the start of the reply HeartbeatMessage:

/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);

So the code writes the response type to the start of the buffer, increments the buffer pointer, uses the s2n() macro to write the 16-bit payload length to memory and increment the buffer pointer by two bytes, and then it copies payload number of bytes from the received payload into the outgoing payload for the reply.

Remember, payload is controlled by the attacker, and it's quite large at 64KB. If the actual HeartbeatMessage sent by the attacker only has a payload of, say, one byte, and its payload_length is a lie, then the above memcpy() will read beyond the end of the received HeartbeatMessage and start reading from the victim process's memory.

And this memory will contain other juicy information, such as passwords or decrypted messages from other clients. Sending another heartbeat message leaks another 64KB, so rinse and repeat to scour the victim's system for goodies.

In fact, the bug leaks this sort of information, although we understand Yahoo! has since patched its systems:

The fix

The patch in OpenSSL 1.0.1g is essentially a bounds check, using the correct record length in the SSL3 structure (s3->rrec) that described the incoming HeartbeatMessage.

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;

OpenSSL's implementation of TLS heartbeats was committed to the project's source code 61 minutes to midnight on Saturday, 31 December, 2011. What we're experiencing now is the mother of all delayed hangovers. ®

Bootnote

There was some confusion over exactly how many bytes were leaked by Heartbleed, given that the maximum TLS record length is 16KB. However, this situation being the clusterf*ck that it is, OpenSSL will happily spaff 64KB back to you if you ask nicely.

Protecting users from Firesheep and other Sidejacking attacks with SSL

More from The Register

next story
Spies would need SUPER POWERS to tap undersea cables
Why mess with armoured 10kV cables when land-based, and legal, snoop tools are easier?
Early result from Scots indyref vote? NAW, Jimmy - it's a SCAM
Anyone claiming to know before tomorrow is telling porkies
Jihadi terrorists DIDN'T encrypt their comms 'cos of Snowden leaks
Intel bods' analysis concludes 'no significant change' after whistle was blown
Israeli spies rebel over mass-snooping on innocent Palestinians
'Disciplinary treatment will be sharp and clear' vow spy-chiefs
TOR users become FBI's No.1 hacking target after legal power grab
Be afeared, me hearties, these scoundrels be spying our signals
Hackers pop Brazil newspaper to root home routers
Step One: try default passwords. Step Two: Repeat Step One until success
China hacked US Army transport orgs TWENTY TIMES in ONE YEAR
FBI et al knew of nine hacks - but didn't tell TRANSCOM
Microsoft to patch ASP.NET mess even if you don't
We know what's good for you, because we made the mess says Redmond
NORKS ban Wi-Fi and satellite internet at embassies
Crackdown on tardy diplomatic sysadmins providing accidental unfiltered internet access
prev story

Whitepapers

Providing a secure and efficient Helpdesk
A single remote control platform for user support is be key to providing an efficient helpdesk. Retain full control over the way in which screen and keystroke data is transmitted.
WIN a very cool portable ZX Spectrum
Win a one-off portable Spectrum built by legendary hardware hacker Ben Heck
Saudi Petroleum chooses Tegile storage solution
A storage solution that addresses company growth and performance for business-critical applications of caseware archive and search along with other key operational systems.
Protecting users from Firesheep and other Sidejacking attacks with SSL
Discussing the vulnerabilities inherent in Wi-Fi networks, and how using TLS/SSL for your entire site will assure security.
Security for virtualized datacentres
Legacy security solutions are inefficient due to the architectural differences between physical and virtual environments.