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 a web 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 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 other scripts as a shell command. While extremely useful, this functionality can be dangerous when used incorrectly and lead to web application security problems, as explained in this article.
Why you should be careful with system commands in web applications
By exploiting a command injection vulnerability in a vulnerable application, attackers can add extra 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 extremely careful when passing user input to one of those functions when developing web applications.
Command injection vulnerability example
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 will be 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 this:
ping -c 5 "$(id)"
The above code injection returns a response like:
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 an 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 combined with context-depended encoding is always a must to ensure your web application code is not vulnerable to other high-impact vulnerabilities, including cross-site scripting (XSS) and SQL injection.
If you don’t need system command functionality, deactivate it in your configuration to eliminate the risk of attackers getting access to the system shell on the host operating system through vulnerable web applications. Depending on the technology, you may be able to separate the execution of the process from the input parameters. You can also build a whitelist of possible inputs and check the formats, for example accepting only integers for a numeric identifier.
Vulnerability classification and severity table
|ID / Severity