Answer by Samuel Jones:
I am not an expert (by any means) in network security, but it looks like the actual bug here is pretty easy to understand.
The Heartbleed bug is in OpenSSL's TLS heartbeat implementation. Generally, the goal of this heartbeat is to be able to verify that a connection is still open by sending some sort of arbitrary message and expecting a response to it.
When a TLS heartbeat is sent, it comes with a couple notable pieces of information:
- some arbitrary payload data. This is intended to be repeated back to the sender so the sender can verify the connection is still alive and the right data is being transmitted through the communication channel.
- the length of that data, in bytes (16 bit unsigned int). We'll call it len_payload.
The OpenSSL implementation used to do the following in a nutshell, best as I can tell (leaving out non-relevant steps):
- Allocate a heartbeat response, using len_payload as the intended payload size
- memcpy() len_payload bytes from the payload into the response.
- Send the heartbeat response (with all len_payload bytes) happily back to the original sender.
The problem is that the OpenSSL implementation never bothered to check that len_payload is actually correct, and that the request actually has that many bytes of payload. So, a malicious person could send a heartbeat request indicating a payload length of up to 2^16 (65536), but actually send a shorter payload. What happens in this case is that memcpy ends up copying beyond the bounds of the payload into the response, giving up to 64k of OpenSSL's memory contents to an attacker.
It appears that this never actually segfaults because, for whatever reason, OpenSSL has a custom implementation of malloc that is enabled by default. So, the next memory addresses out of bounds of the received request are likely part of a big chunk of memory that custom memory allocator is managing and thus would never be caught by the OS as a segmentation violation. (I could be a bit off here, as I haven't looked at SSL's memory allocator.)
What's in this extra 64k memory? It depends. You could get nothing useful on any one faked heartbeat. However, nothing stops you from sending as many fake heartbeats as your (fake) heart desires. People have demonstrated that you can get unencrypted network traffic (including passwords), private security keys, and other things that people depend upon for security.
The fix () as linked in 's answer implements checking on the length of the payload, and silently fails (sends no response) if len_payload is incorrect or out-of-spec. This makes sense, as if a valid heartbeat was sent and an invalid one was received, you should assume that some data was corrupted/lost along the way, that the connection is no good, and thus not send a heartbeat response.