Updated: Dec 31, 2022
In the previous lesson in this module, we explored the basics of buffer overflows. We defined buffer overflows and looked at the fundamental theory behind the buffer overflow. In addition, we looked at how dangerous and persistent these buffer overflow attacks can be by examining how many critical vulnerabilities are related to buffer overflows.
In this lesson, we will design and run a simple buffer overflow to demonstrate how the principles we learned in Part 1 can be applied. We will be using our Kali Linux system to develop some simple stack overflows in C . Note that this is a simple buffer overflow to demonstrate the concepts. It is far from a working exploit, but I believe that it demonstrates clearly how a buffer overflow can be used for malicious purposes without going into great detail and more programming. We will leave those for later lessons.
II. Open an IDE
Since we will be writing some simple C code in this lesson, you will probably want to use an IDE or Integrated Development Environment. Of course, you can simple use a text editor, but an IDE tends make coding a bit simpler. Whatever works for you is fine. For these lessons and exercises, I will be using the "MonoDevelop" IDE that is built into Kali. Different versions of Kali have different IDE's built in. Generally, each of them will work. In addition, you can download and install other popular IDE's such as Eclipse.
We can find it be going to Applications -->Programming --> MonoDevelop and clicking as seen in the screenshot below.
MonoDevelop will open a GUI like that below. We can now select to "Start a new solution".
I will call my solution "SimpleBufferOverlow" and then start a new file and also call it "SimpleBufferOverflow.c". Next, click on C and select "Empty C Project". Click OK.
This should open a new blank coding screen. Note that MonoDevelop will create a new directory with the same name as the "Solution" to store your files. Now, we want to add our C code. You can now use the IDE similar to any text editor.
III. Writing our Buffer Overflow
This basic program we are about to create simply creates two variables, "website" and "command" (Lines #5 and #6), and allocates a fixed amount of memory to them using the C function malloc (memory allocation). It then prints the memory location of each these two variables (Lines #11 and#12). Next, it then calculates and prints the distance between the two memory areas (Line #14). Next, it prompts the user asking "what is the best place to learn hacking" (Line 15) and when the user answers, it places that input into the "website" variable (Line 17). Finally, it prints a statement regarding the best place to learn hacking with the input from the user (Line 19). In the very last line, it executes what is in the "command" variable (Line 21), if anything.
When you have completed this code, save it and call it "SimpleBufferOverflow.c". To be able to execute it, we will need to give ourselves permission to execute. In Linux, this can be done with the chmod command as seen below.
kali >chmod 755 SimpleBufferOverflow.c
Next , we need to compile the code with gcc. Gcc is a built-in GNU C compiler in Kali. Let's use it to compile our simple program and save it (-o) to a new file named "SimpleBufferOverflow" (without the .c extension).
kali > gcc SimpleBufferOverflow.c -o SimpleBufferOverflow
Now, let's run this simple program.
Color added for emphasis
The program calculated the amount of memory between the website variable and the command variable. As you can see, it is 16 bytes. Then, the program asks the user ;
"Where is the best place on Earth to learn hacking?"
Of course, the user answers "hacker-arise.com". The user's input then goes into the variable "website" and the program finishes by using that input into the "website" variable and prints out the statement;
"The best place on Earth to learn is hacking is hackers-arise.com".
Everything worked perfectly fine, just as expected.
IV. Overflow the Website Variable
In the previous program, both the "website" and "command" variables were of fixed length defined by the malloc function. Our simple program calculated the difference between the memory locations of these two variables. What would happen if the input into the website variable were larger than the allotted space of 16 bytes and ran into the command variable's memory space? Let's try it and see what happens.
We know that there are 16 bytes between the two memory locations. So, let's try entering some input that is more than 16 bytes/characters long (ASCII characters are 1 byte). For instance, let's just try putting in 17 random characters when prompted for our favorite website (the process of sending random input to a program and its variables is referred to as fuzzing. We will look at fuzzing and some fuzzing tools in later lessons to attempt to find potential buffer overflows in the real world).
Enter the following or any random 17 characters when prompted.
As you can see, our SimpleBufferOverflow worked fine until it came to the last line. In that line of code, it attempts to execute whatever is in the "command" variable. Earlier, there was nothing in this variable and nothing executed, but now it appears to execute "j" and it responds with "not found". It is telling us that it did not find any commands "j". As you can see, our 17th character in our input "j" actually overflowed to the "command" variable memory area and our program attempted to execute it. This is useful information that we might be able to use as an attacker!
If everything that comes after the 16th character in our input to the "website" prompt is stored in a fixed size variable "website" and then overflows into the command variable, we might be able to use this knowledge against the program and, ultimately, the system.
Let's see whether we can get the system to execute an "ifconfig". All we need to do is type 16 random characters followed by "ifconfig" and we may be able get the networking info from the underlying system. Let's give it a try.
As you can see, the SimpleBufferOverflow program overflowed the "website" variable and placed the everything after the 16th character, in this case "ifconfig", into the "command" variable and then executed it. As a result, we were able to get the networking information from the underlying system!
The point we are trying make here is that without bounds on the variable, when excess input overflows the variable, the attacker may be able to get their code executed by the system.
That was pretty innocuous. What if we were more malicious and wanted to get the password hashes. Of course, to get the password hashes our program would need root privileges, if even only for that very moment that it executes. This does happen as some programs do have the SUID bit set that gives them the privileges of the creator. To find programs with the SUID bit set for "root", trying running the following command.
kali >find / -perm +4000 -user root -type f -print
As you can see, there numerous files that operate with the SUID bit set as root. My point here is that if we could overflow of buffer in those programs (and it has been done!), we could execute our commands as root!
Now, let's see if we can get those password hashes stored in /etc/shadow. Let's assume that this program has the SUID bit set for the "root" user. This means that when it executes, it is executing with the privileges of the creator, "root". We will need to first give the variable 16 characters of any input. Then, the 17th character will overflow the "website" variable into "command".
Notice that the 17-19 characters are "cat", followed /etc/shadow (the location of the password hashes in Linux). If we can get this to execute, it should display the entire contents of the /etc/shadow file on screen.
It worked! We now have all the hashed passwords . Note that on my system, only the root user has a hashed password. All of the other users do not yet have passwords. If they did, their hashed passwords would appear here as well.
If you wanted to really malicious, you could type when prompted for "the best place to study hacking" ;
qwertyuiopasdfghdd if=/dev/random of=/dev/sda
What do you think this command would do if executed?
This exercise was meant to demonstrate how a buffer overflow can be used by an attacker to execute their code or commands if the variables are unbounded.In the next few articles in this series, we will look at fuzzing and fuzzers to attempt to find unbounded variables that can be overflowed.