Memra

TLS attacks, Heartbleed, HTTPS, and what TLS 1.3 changed

◈ 8 cards

The four categories of attack on TLS, the exact Heartbleed mechanism, what HTTPS does and does not encrypt, and an honest account of how TLS 1.3 differs from the handshake the paper examines.

Four places TLS gets attacked

A protocol is attacked where it is implemented, not where it is specified. The four categories worth naming:

  1. Attacks on the Handshake Protocol — exploiting the formatting and implementation of the RSA encryption scheme, a line of attack running from 1998 onward and refined over the years to defeat the countermeasures added against it.
  2. Attacks on the record and application data protocols — a chosen-plaintext attack against the record layer (guess a plaintext associated with a known ciphertext), and a compression-based attack that recovers the contents of web cookies when compression is used with TLS, which against an authentication cookie yields session hijacking.
  3. Attacks on the PKI — certificate validation is hard, and widely used TLS libraries have shipped vulnerable certificate-validation implementations. The cryptography is fine; the check around it is not.
  4. Denial of service — overwhelming a server with handshake requests and renegotiations. It works because most of the handshake computation falls on the server, so the attack costs the attacker far less than it costs the target. This is cost asymmetry, the same principle behind every resource-exhaustion attack.

Heartbleed, step by step

The Heartbeat Protocol exists to check that a quiet peer is still alive and to keep idle connections from being closed by a firewall. A heartbeat_request carries a payload length field, a payload of between 16 bytes and 64 KB, and some padding, and the responder must echo an exact copy of the payload back.

Worked example — the bug, in four moves. A vulnerable OpenSSL server receives a heartbeat request. It:

  1. reads the incoming request;
  2. allocates a buffer sized by the declared payload length;
  3. overwrites that buffer with the message it actually received;
  4. returns the declared length of data back to the requester.

There is no step that compares the declared length with the actual message size. So an attacker sends a request declaring the maximum, 64 KB, while including only the minimum payload, 16 bytes. The server allocates ~64 KB, overwrites 16 bytes of it, and returns all ~64 KB — leaving 65,519 bytes of whatever was previously in that memory flowing back to the attacker. Repeat the request and you get a different slice of memory each time.

Four properties made it catastrophic rather than merely embarrassing. The leaked memory could hold private keys, user identification data, authentication material and passwords. It went undiscovered for years. It is trivially easy to exploit. And it leaves no trace in any log, because a heartbeat is a perfectly ordinary message.

Say the classification out loud, because it is examinable: Heartbleed was an implementation bug in one library's Heartbeat handler — not a flaw in the TLS specification. The design was fine. The code trusted a length field supplied by the other end.

HTTPS: what is actually encrypted

HTTPS is HTTP over TLS, documented in RFC 2818. Ordinary HTTP uses port 80; HTTPS uses port 443 and the https:// scheme. The HTTP client is also the TLS client: it opens TCP, sends ClientHello, completes the handshake, and only then issues its first request — with all HTTP data travelling as TLS application data.

Five things are encrypted: the URL of the requested document, the document's contents, the contents of browser forms, cookies in both directions, and the contents of the HTTP headers. What is not encrypted is the destination IP address, which routers plainly must read.

The URL is the one learners get wrong. The confusion comes from the fact that the hostname has historically leaked by other routes — through DNS lookups and through the Server Name Indication field in the handshake, which is sent before any encryption is available. Both facts are true at once: the hostname may leak, and the full URL — path, query string and all — is inside the encryption. Being able to say both is the answer.

Closure has a security edge too. At the TLS level each side should send a close_notify alert. An implementation may close without waiting, giving an incomplete close. But a client that finds the TCP connection torn down with neither a close_notify nor a Connection: close must treat it as possible evidence of a truncation attack and issue a security warning — a missing goodbye is not automatically innocent.

What TLS 1.3 changed — and why this section is separate

The four-phase handshake in L14.5 is the SSLv3 / TLS 1.2 lineage. It is what the paper examines, and you should be able to reproduce it. It is also not the current protocol, and it would be dishonest to leave it as though it were. TLS 1.3 (RFC 8446, 2018) made four changes worth naming:

  • One round trip. The client guesses a key-exchange group and sends its key share with ClientHello, so the server can reply with its share, its certificate and Finished in a single flight. Two round trips became one; a resumed session can send data with the very first flight.
  • Static RSA key exchange removed, along with the older cipher suites, and the suite list cut down to a handful of AEAD constructions. Every remaining key exchange is ephemeral, so forward secrecy is mandatory rather than optional — recovering a server's long-term key no longer decrypts recorded traffic.
  • Compression removed, which retires the compression-based cookie-recovery attack outright rather than mitigating it.
  • Everything after ServerHello is encrypted — the certificate included. And change_cipher_spec survives only as a middlebox-compatibility no-op: bytes on the wire that mean nothing, sent so that network equipment expecting a 1.2 handshake does not drop the connection.

When an exam question asks for "the four-phase handshake", give the 1.2-era one. When a question asks what changed, or when you are designing something real, this list is the answer.

1. Read requestdeclared length 65,535 · payload 16 bytes2. Allocate by DECLARED lengthbuffer holds stale memory3. Overwrite with what arrivedonly 16 bytes are replaced4. Return DECLARED length65,519 bytes of old memory go backThe missing step: compare declared againstactual.
Step 2 sizes the buffer from a number the attacker chose. Step 3 fills only what actually arrived. The gap between them is the leak.

source EXT — RFC 8446

CategoryExampleWhat addressed ithandshakeRSA formatting attackspadding checks; 1.3 dropsstatic RSArecord / app datacompression cookie recovery1.3 removes compressionPKIweak cert validation inlibrariesfixed validation codedenial of servicehandshake / renegotiationfloodrate limits, cost limitsHeartbleed sits outside all four — it is a library bug in an extension.
Three of the four are implementation problems rather than specification problems — which is the lesson of the whole section.

source EXT — RFC 8446

source EXT — RFC 8446

NORMAL ~/memra/learn/comp-400/tls-attacks-heartbleed-https-and-what-tls-1-3-changed utf-8 LF