The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
This weakness can lead to a vulnerability in environments in which the attacker does not have direct access to the operating system, such as in web applications. Alternately, if the weakness occurs in a privileged program, it could allow the attacker to specify commands that normally would not be accessible, or to call alternate commands with privileges that the attacker does not have. The problem is exacerbated if the compromised process does not follow the principle of least privilege, because the attacker-controlled commands may run with special system privileges that increases the amount of damage. There are at least two subtypes of OS command injection: The application intends to execute a single, fixed program that is under its own control. It intends to use externally-supplied inputs as arguments to that program. For example, the program might use system("nslookup [HOSTNAME]") to run nslookup and allow the user to supply a HOSTNAME, which is used as an argument. Attackers cannot prevent nslookup from executing. However, if the program does not remove command separators from the HOSTNAME argument, attackers could place the separators into the arguments, which allows them to execute their own program after nslookup has finished executing. The application accepts an input that it uses to fully select which program to run, as well as which commands to use. The application simply redirects this entire command to the operating system. For example, the program might use "exec([COMMAND])" to execute the [COMMAND] that was supplied by the user. If the COMMAND is under attacker control, then the attacker can execute arbitrary commands or programs. If the command is being executed using functions like exec() and CreateProcess(), the attacker might not be able to combine multiple commands together in the same line. From a weakness standpoint, these variants represent distinct programmer errors. In the first variant, the programmer clearly intends that input from untrusted parties will be part of the arguments in the command to be executed. In the second variant, the programmer does not intend for the command to be accessible to any untrusted party, but the programmer probably has not accounted for alternate ways in which malicious attackers can provide input.
Threat Mapped score: 0.0
Industry: Finiancial
Threat priority: Unclassified
CVE: CVE-2020-10987 — KEV
OS command injection in Wi-Fi router, as exploited in the wild per CISA KEV.
CVE: CVE-2020-10221 — KEV
Template functionality in network configuration management tool allows OS command injection, as exploited in the wild per CISA KEV.
CVE: CVE-2020-9054 — KEV
Chain: improper input validation (CWE-20) in username parameter, leading to OS command injection (CWE-78), as exploited in the wild per CISA KEV.
CVE: CVE-1999-0067
Canonical example of OS command injection. CGI program does not neutralize "|" metacharacter when invoking a phonebook program.
CVE: CVE-2001-1246
Language interpreter's mail function accepts another argument that is concatenated to a string used in a dangerous popen() call. Since there is no neutralization of this argument, both OS Command Injection (CWE-78) and Argument Injection (CWE-88) are possible.
CVE: CVE-2002-0061
Web server allows command execution using "|" (pipe) character.
CVE: CVE-2003-0041
FTP client does not filter "|" from filenames returned by the server, allowing for OS command injection.
CVE: CVE-2008-2575
Shell metacharacters in a filename in a ZIP archive
CVE: CVE-2002-1898
Shell metacharacters in a telnet:// link are not properly handled when the launching application processes the link.
CVE: CVE-2008-4304
OS command injection through environment variable.
CVE: CVE-2008-4796
OS command injection through https:// URLs
CVE: CVE-2007-3572
Chain: incomplete denylist for OS command injection
CVE: CVE-2012-1988
Product allows remote users to execute arbitrary commands by creating a file whose pathname contains shell metacharacters.
N/A
Phase | Note |
---|---|
Implementation | REALIZATION: This weakness is caused during implementation of an architectural security tactic. |
Intro: This example code intends to take the name of a user and list the contents of that user's home directory. It is subject to the first variant of OS command injection.
Body: The $userName variable is not checked for malicious input. An attacker could set the $userName variable to an arbitrary OS command such as:
$userName = $_POST["user"]; $command = 'ls -l /home/' . $userName; system($command);
Intro: The following simple program accepts a filename as a command line argument and displays the contents of the file back to the user. The program is installed setuid root because it is intended for use as a learning tool to allow system administrators in-training to inspect privileged system files without giving them the ability to modify them or damage the system.
Body: Because the program runs with root privileges, the call to system() also executes with root privileges. If a user specifies a standard filename, the call works as expected. However, if an attacker passes a string of the form ";rm -rf /", then the call to system() fails to execute cat due to a lack of arguments and then plows on to recursively delete the contents of the root partition.
int main(int argc, char** argv) { char cmd[CMD_MAX] = "/usr/bin/cat "; strcat(cmd, argv[1]); system(cmd); }
Intro: 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.
Body: Suppose an attacker provides a domain name like this:
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); }
Intro: The example below reads the name of a shell script to execute from the system properties. It is subject to the second variant of OS command injection.
Body: If an attacker has control over this property, then they could modify the property to point to a dangerous program.
String script = System.getProperty("SCRIPTNAME"); if (script != null) System.exec(script);
Intro: In the example below, a method is used to transform geographic coordinates from latitude and longitude format to UTM format. The method gets the input coordinates from a user through a HTTP request and executes a program local to the application server that performs the transformation. The method passes the latitude and longitude coordinates as a command-line option to the external program and will perform some processing to retrieve the results of the transformation and return the resulting UTM coordinates.
Body: However, the method does not verify that the contents of the coordinates input parameter includes only correctly-formatted latitude and longitude coordinates. If the input coordinates were not validated prior to the call to this method, a malicious user could execute another program local to the application server by appending '&' followed by the command for another program to the end of the coordinate string. The '&' instructs the Windows operating system to execute another program.
public String coordinateTransformLatLonToUTM(String coordinates) { String utmCoords = null; try { String latlonCoords = coordinates; Runtime rt = Runtime.getRuntime(); Process exec = rt.exec("cmd.exe /C latlon2utm.exe -" + latlonCoords); // process results of coordinate transform // ... } catch(Exception e) {...} return utmCoords; }
Intro: The following code is from an administrative web application designed to allow users to kick off a backup of an Oracle database using a batch-file wrapper around the rman utility and then run a cleanup.bat script to delete some temporary files. The script rmanDB.bat accepts a single command line parameter, which specifies what type of backup to perform. Because access to the database is restricted, the application runs the backup as a privileged user.
Body: The problem here is that the program does not do any validation on the backuptype parameter read from the user. Typically the Runtime.exec() function will not execute multiple commands, but in this case the program first runs the cmd.exe shell in order to run multiple commands with a single call to Runtime.exec(). Once the shell is invoked, it will happily execute multiple commands separated by two ampersands. If an attacker passes a string of the form "& del c:\\dbms\\*.*", then the application will execute this command along with the others specified by the program. Because of the nature of the application, it runs with the privileges necessary to interact with the database, which means whatever command the attacker injects will run with those privileges as well.
... String btype = request.getParameter("backuptype"); String cmd = new String("cmd.exe /K \" c:\\util\\rmanDB.bat " +btype+ "&&c:\\utl\\cleanup.bat\"") System.Runtime.getRuntime().exec(cmd); ...
Intro: The following code is a wrapper around the UNIX command cat which prints the contents of a file to standard out. It is also injectable:
Body: Used normally, the output is simply the contents of the file requested, such as Story.txt:
#include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { char cat[] = "cat "; char *command; size_t commandLength; commandLength = strlen(cat) + strlen(argv[1]) + 1; command = (char *) malloc(commandLength); strncpy(command, cat, commandLength); strncat(command, argv[1], (commandLength - strlen(cat)) ); system(command); return (0); }