OS command injection (also known as shell injection) is a web security vulnerability that allows an attacker to execute arbitrary operating system (OS) commands on the server that is running an application, and typically fully compromise the application and all its data.
Why Do Web Applications Need to Execute System Commands?
Web applications sometimes need to execute operating system commands (OS commands) to communicate with the underlying host operating system and the file system. This can be done to run system commands, launch applications written in another programming language, or run shell, python, perl, or PHP scripts. For any operating system, including Windows, Unix and Linux, functions are available that can execute a command that is passed to the other scripts as a shell command. While extremely useful, this functionality can be dangerous when used incorrectly, and can lead to web application security problems, as explained in this article.
Why You Should be Careful When Using System Commands in Web Applications
By exploiting a command injection vulnerability in a vulnerable application, attackers can add additional commands or inject their own operating system commands. This means that during a command injection attack, an attacker can easily take complete control of the host operating system of the web server. Therefore, developers should be very careful how to pass user input into one of those functions when developing web applications.
Example of a Command Injection Vulnerability
In this example of the command injection vulnerability, we are using the ping functionality, which is notoriously insecure on many routers. Imagine a vulnerable application that has a common function that passes an IP address from a user input to the system's ping command. Therefore, if the user input is 127.0.0.1, the following command is executed on the host operating system:
ping -c 5 127.0.0.1
Since we are dealing with a vulnerable web application, it is possible to break out of the ping command or provoke an error that returns useful information to the attacker. The attacker can then use this functionality to execute his own arbitrary commands. An example of adding additional system commands could look like this:
ping -c 5 127.0.0.1; id
In the above example, first the ping command is executed and directly after that the id command execution takes place. Therefore the command output on the page will look like this:
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.023 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.072 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.037 ms
--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.023/0.056/0.074/0.021 ms
uid=0(root) gid=0(root) groups=0(root)
During an OS command injection attack, the attacker can also set up an error based attack. For example, a code injection in this case will typically look like the below:
ping -c 5 "$(id)"
The above code injection returns a response like this:
ping: unknown host uid=0(root) gid=0(root) groups=0(root)
How to Prevent System Command Injection Vulnerabilities
In order to prevent an attacker from exploiting a vulnerable web application and inserting special characters into the operating system command, you should try to generally avoid system calls where possible. In all cases, avoid user input of any kind unless it is absolutely necessary. And if it is necessary, make sure there is proper input validation in place – input validation is always a must to ensure your web application code is not vulnerable to other high-impact vulnerabilities, including XSS and SQL Injection.
Also, deactivate this functionality in your language's configuration file if you don't need it, so attackers can never manage to gain access to the system shell on the host operating system through vulnerable web applications. In some languages, you can separate the execution of the process from the input parameters. You can also build a white list of possible inputs and check the formats, for example accepting only integer for a numeric id.
Vulnerability Classification and Severity Table
|Classification||ID / Severity|