In: Computer Science
Computer and Internet Security: a Hands on Approach
5.3 Instead of jumping to the system() function, we would like to jump to the execve() function to execute "/bin/sh". Please describe how to do this. You are allowed to have zeros in your input (assume that memcpy() is used for memory copy, instead of strcpy())
Instead of jumping to thesystem()function, we would like to jump to theexecve()function to execute"/bin/sh"
As we know, thesystem()function calls/bin/sh, which is a symbolic link to/bin/bash. Recent versions of bash will drop the privilege if it detects that the effective user ID and the real user ID are different. .
When launching the return-to-libc attack, instead of jumping to the beginning of the system()function, an attacker causes the program to jump to the first instruction right after the function prologue in the system()function.
An example of such would be to exploit a buffer overflow bug to overwrite EIP with the address of system() or execl() included in the libc library to run an interactive shell (/bin/sh for example). This idea is quite reasonable, and since it does not involve estimating return addresses and building large exploit buffers, this is quite an appealing technique
Let's say we have the following small example program, vulnprog:
--START
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("Usage: %s <string>\n", argv[0]);
exit(-1);
}
char buf[5];
strcpy(buf, argv[1]);
return(0);
}
gcc vulnprog.c -o vuln prog
chown root vuln prog
chmod +s vuln prog
--END
Anyone with a small bit of knowledge of buffer overflows can see that thepreceding program is ridiculously insecure, and allows anybody who exceeds thebounds of `buf' to overwrite data on the stack. It would usually be quite easyto write an exploit for the above example program,
Now, we get rid off this voluprog using Computer and Internet Security: a Hands on Approach keep in mind and we actually get the information we need and prepare an'exploit buffer' in order to execute a libc function as a result of a buffer all we need is the address of the desired libc function, andthe address of any function arguments. So let's say for example we wanted toexploit the above program (it is SUID root) to execute a shell (we want /bin/sh)using system() - all we'd need is the address of system() and then the addressholding the string "/bin/sh" right? Correct.
--START
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("Usage: %s <environ_var>\n", argv[0]);
exit(-1);
}
char *addr_ptr;
addr_ptr = getenv(argv[1]);
if(addr_ptr == NULL) {
printf("Environmental variable %s does not exist!\n",
argv[1]);
exit(-1);
}
printf("%s is stored at address %p\n", argv[1], addr_ptr);
return(0);
}
--END
Now, let's get down to actually creating our variable
with the desired string "/bin/sh" and get the address of it.
First I create the environmental variable, and then I run our
above program to
get the memory location of a desired environment variable:
We need a plan: instead of using 'system()' to run a shell,
we'll overwrite the return address on the stack (EIP register) with
the address of 'execl()' function in the libc library. We'll tell
'execl()' to execute our wrapper program
(expl_wrpper.c), which raises our privs and executes a shell.
Voila, a root shell. However, this is not going to be as easy as
the last experiment. For a start, the execl() function needs NULLs
as the last function argument, but
'strcpy()' in vulnprog.c will think that a NULL (\x00 in hex
representation) means the end of the string, thus making the
exploit fail. Instead, we can use 'printf()' to write NULLs without
NULL's appearing in the exploit buffer.