COP4610: Operating Systems & Concurrent Programming up ↑

Buffer Overflow in Heartbleed Vulnerability

 

The following text is reproduced here from Robert Secord's blog (http://blog.sei.cmu.edu/post.cfm/secure-coding-prevent-vulnerabilities-125 on the CERT Secure Coding website. It is a recent example of how one small oversight in a piece of C code can cause tremendous social, political, and econonmic damage. I recommend you follow the link to read the full blog, and explore the website, especially the CERT Secure C Coding Standard https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Coding+Standard.

Heartbleed emerged as a serious vulnerability in the popular OpenSSL cryptographic software library. This vulnerability allows an attacker to steal information that under normal conditions would be protected by Secure Socket Layer/Transport Layer Security (SSL/TLS) encryption.

Despite the seriousness of the vulnerability, Heartbleed is the result of a common programming error and an apparent lack of awareness of secure coding principles. Following is the vulnerable code:

int dtls1_process_heartbeat(SSL *s) {
unsigned char *p = &s->s3->rrec.data[0], *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */

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

/* ... More code ... */

if (hbtype == TLS1_HB_REQUEST) {
unsigned char *buffer, *bp;
int r;

/*
* Allocate memory for the response; size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding.
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
bp = buffer;

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

/* ... More code ... */
}
/* ... More code ... */
}

This code processes a “heartbeat” packet from a client or server. As specified in the Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension RFC 6520, when the program receives a heartbeat packet, it must echo the packet’s data back to the client. In addition to the data, the packet contains a length field that conventionally indicates the number of bytes in the packet data, but there is nothing to prevent a malicious packet from lying about its data length.

The p pointer, along with payload and p1, contain data from a packet. The code allocates a buffer sufficient to contain payload bytes, with some overhead, then copies payload bytes starting at p1 into this buffer and sends it to the client. Notably absent from this code are any checks that the payload integer variable extracted from the heartbeat packet corresponds to the size of the packet data. Because the client can specify an arbitrary value of payload, an attacker can cause the server to read and return the contents of memory beyond the end of the packet data, which violates our recommendation, INT04-C, Enforce limits on integer values originating from tainted sources. The resulting call to memcpy() can then copy the contents of memory past the end of the packet data and the packet itself, potentially exposing sensitive data to the attacker. This call to memcpy() violates the secure coding rule ARR38-C, Guarantee that library functions do not form invalid pointers. A version of ARR38-C also appears in ISO/IEC TS 17961:2013, “Forming invalid pointers by library functions [libptr].” This rule would require a conforming analyzer to diagnose the Heartbleed vulnerability.

T. P. Baker. ($Id)