Heartbleed: When Asking Nicely Leaked the Server's Secrets
A missing length check in OpenSSL let anyone read chunks of a server's memory, including private keys and passwords. Here is how Heartbleed (CVE-2014-0160) worked and why it was so serious.
Imagine walking up to a bank teller and saying, "Please read me back the word cat, and while you are at it, read me the next ten thousand words on your desk too." A sensible teller would look at the tiny word you handed over, notice it is only three letters, and refuse. But what if the teller simply trusted your count, grabbed a thick stack of whatever happened to be lying there, and read it all aloud, including other customers' account details and the manager's keys? That is Heartbleed. It is the rare bug that was both catastrophic and beautifully simple to understand. No code was executed and nothing crashed. An attacker just asked the server a slightly dishonest question, and the server politely handed back pieces of its own memory, private keys and passwords included. This is how it worked.
Credit and scope
Heartbleed was discovered independently by Neel Mehta of Google and by the security firm Codenomicon, who gave it its name and logo. It was a flaw in OpenSSL, the library that secures a huge share of the internet. This is a defensive explainer, not original research.
Some background: TLS and OpenSSL
To follow the story, two terms are worth knowing. TLS, short for Transport Layer Security, is the protocol that puts the S in HTTPS. It is the technology that scrambles your connection to a website so that nobody sitting between you and the server can read or tamper with what you send. When you see the little padlock in your browser, TLS is doing its job.
OpenSSL is a software library that provides TLS to a vast number of servers. Rather than every website building its own encryption from scratch, most simply use OpenSSL. That efficiency is wonderful right up until the moment OpenSSL has a bug, because then the same flaw is present on an enormous slice of the internet at once. Heartbleed was exactly that kind of moment.
The feature: a heartbeat
TLS has an optional feature called a heartbeat. It exists to keep a connection alive. Rather than tearing down an encrypted link and rebuilding it, which is expensive, one side can send a small message and ask the other to echo it straight back. If the echo comes back, both sides know the connection is still healthy. It is the digital version of calling out "still there?" and hearing "still here!" in reply.
A heartbeat request says two things. Here is some data, and here is how long that data is. The data might be the word "hello" and the length would then be five. The server reads the length, copies that many bytes, and sends them back.
That length field is the whole story.
The bug: believing the stated length
The attacker sends a heartbeat that lies. It says, "here is 1 byte of data, please echo back 64 kilobytes." The data really is just 1 byte. But vulnerable versions of OpenSSL trusted the claimed length instead of checking it against the data actually sent. So the server copied roughly 64 kilobytes starting from where the tiny message sat in memory, and sent all of it back to the attacker.
Attacker: "Echo this back. Data: 'A'. Length: 65535 bytes."
Server: copies 65535 bytes from memory starting at 'A'...
returns 'A' plus ~65534 bytes of whatever was next to it.That "whatever was next to it" is the problem. To understand why, you need to know a little about how programs use memory. A running program keeps its working data in memory, and it reuses the same space over and over as it handles one request after another. The buffer holding your tiny heartbeat message sits in a busy neighbourhood, surrounded by whatever the server was recently working on. When OpenSSL grabbed 64 kilobytes starting from that spot, it scooped up all the neighbouring data too, whether or not it had anything to do with the attacker.
The server's memory near that buffer could contain almost anything it had touched lately: other users' passwords as they logged in, session cookies that identify logged in users, snippets of private messages, and worst of all, the server's own private key.
Why leaking the private key is the nightmare
A server's private key is the secret that proves its identity and protects its encrypted traffic. If an attacker reads it out of memory, they can impersonate the server and potentially decrypt captured traffic. Heartbleed could leak it silently, leaving no trace in the logs. This is why it scored so highly despite running no code.
The name of the flaw: a buffer over read
This class of bug is called a buffer over read. A buffer is just a labelled box of memory set aside to hold a known amount of data. An over read happens when code reads past the end of that box and keeps going into the memory beside it. The code was supposed to read one byte and instead read tens of thousands, spilling out of its own box and into its neighbours' boxes.
Two details made Heartbleed especially cruel. First, it was silent. A normal attack often leaves fingerprints in the logs, but a heartbeat request is ordinary traffic, so the leak looked like routine keep alive chatter. Second, it was repeatable. The attacker could send the request again and again, harvesting a fresh 64 kilobytes of memory each time. Patience alone was enough to eventually sweep up something valuable, because memory keeps churning as the server works.
The root cause in one sentence
Never trust a size, length, or count that came from the other side of the wire. Always check the number the sender claims against the data they actually sent before you act on it. That single habit would have stopped Heartbleed cold.
Cleaning up
Because the leak was invisible, patching alone was not enough. If the private key might already be in an attacker's hands, quietly installing the fix would not undo the theft. The full response had three parts.
- Update OpenSSL. The fix landed in version 1.0.1g, which simply validates that the claimed length matches the real data before copying anything. It is the missing check, finally added.
- Assume the keys were exposed. Any private key on a vulnerable server had to be treated as compromised, which meant revoking and reissuing certificates with fresh keys. Revoking tells the world the old certificate is no longer trustworthy, and reissuing generates a brand new key that the attacker never saw.
- Rotate everything else. Passwords and session tokens that could have been sitting in memory needed resetting. This is why so many services asked their users to change their passwords in 2014. It was not a drill, it was a precaution against secrets that may already have leaked.
Silent bugs change the maths
With a noisy attack you can often tell whether you were hit. With a silent one you usually cannot, so you have to assume the worst. That is why Heartbleed's cleanup was so painful and so widespread. When you cannot prove a secret is safe, you have to treat it as burned and replace it.
Heartbleed is a favourite teaching example because it pairs so well with other famous bugs that share a theme. Shellshock shows attacker controlled input being trusted by a shell, and Log4Shell shows attacker controlled input being trusted by a logging library. In every case the failure is the same shape, which is trusting something that came from outside without checking it.
The takeaway
Heartbleed came down to a single missing check, trusting a length that the attacker supplied. The lesson runs through all of security. Never assume that attacker controlled input is honest, and always validate a length or size before you act on it. It is also a reminder that a confidentiality bug with no code execution can still be one of the worst days on the internet, because secrets, once leaked silently, are very hard to un leak.