OS Command Injection

Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application. Command injection attacks are possible largely due to insufficient input validation.

OS Command injection examples

This example is a web application that intends to perform a DNS lookup of a user-supplied domain name. It is subject to the first variant of OS command injection.

use CGI qw(:standard);
$name = param('name');
$nslookup = "/path/to/nslookup";
print header;
if (open($fh, "$nslookup $name|")) {
while (<$fh>) {
print escapeHTML($_);
print "<br>\n";
}
close($fh);
}

Suppose an attacker provides a domain name like this: cwe.mitre.org%20%3B%20/bin/ls%20-l

The “%3B” sequence decodes to the “;” character, and the %20 decodes to a space. The open() statement would then process a string like this: /path/to/nslookup cwe.mitre.org ; /bin/ls -l

As a result, the attacker executes the “/bin/ls -l” command and gets a list of all the files in the program’s working directory. To make matters worse, a more dangerous payload can be crafted to perform more severe malicious actions.
This code didn’t validate or sanitize the user input before using it in the execute command. Hence the attacker was able to run the desired command on the server.

How to prevent OS Command Injection attacks?

Ideally, a developer should use existing APIs for their relevant programming languages.

For example, while programming with Java, the developer should use the available Java API located at javax.mail.*. If no such available API exists, the developer should validate the input using Regex or a whitelist of accepted values. This is much better than using Runtime.exec() (see code below) to issue a ‘mail’ command.

Class Win32 extends OS {
                 public void email (String subject, String body) throws Exception {
                                 String cmd = "cmd.exe /c start \"\"\"" + formatMailto(subject, body) + "\"";
                                 Runtime.getRuntime().exec(cmd);
                 }
 }

When it’s not technically possible to remove the command execution, the best way to stay protected is to execute only static strings that do not include user input.