What Causes Command Injection Vulnerabilities? (How are Data and Code Handled in Execution Environments)
This article provides an overview of how command injection vulnerabilities occur and what are some of the causes for command injection vulnerabilities. As mentioned in the previous article, command injection vulnerabilities are one of the most dangerous web vulnerabilities and thus it is important for developers to understand the causes, to be able to avoid these vulnerabilities.
What causes command injection?
Following are two most common reasons why Command Injections occur in web applications.
- Applications taking operating system commands as input and executing them.
- Applications taking data from the user and executing them as OS commands without properly validating.
Let us discuss these two items in detail.
Applications taking OS commands as input:
Let us consider PHP File Manager 0.9.8 as an example. When opened in a browser, it looks as follows.
As you can notice in the preceding picture, there is an option to Execute command. Clicking this button, shows the following.
As we can see, there is an option to execute commands. If a user enters any operating system commands, they will be executed by the underlying operating system as follows.
As we can see in the main menu of the application, there is another feature where the application allows the user to get an interactive shell and users can execute commands as shown in the following figure.
Clearly, features like these, which come by design will cause command injection attacks.
Applications taking data and executing it as commands:
The previous example shows an example of how commands can be taken as user input and executed by the applications. Developers are often aware of such features in their applications, as they get introduced by design.
Now, let us consider the following URL from an application, where the user enters data to be encoded by the application.
This user input is passed as a get parameter to encode.php file.
Following is the source code of encode.php
system("echo -n". $input." | base64");?>
As we can notice from the preceding code snippet, the user input is passed to the php system() function, which is used to execute operating system commands in PHP.
The application is expecting data as user input so that it can be processed by the application. However, let us consider the following URL with an operating system command appended to user data.
If the application receives this input and treats it as data, there is no problem. The entire user supplied input will be base64 encoded and it will be returned back to the user.
However, if the application receives this input and treats it as code instead of data, that will cause command injection.
Let us closely observe what happens when the preceding URL is used by a user. The following is passed as an argument to PHP system() function.
As we can notice in the preceding excerpt, the argument is splitted into two different commands. The data test;id is passed to the application and because of the shell metacharacter (;) the text id turns into code and the output of the command id will be passed to base64 command.
Following is the response returned to the user.
As we can see the word test is not encoded but there is a long encoded text returned in response, because the output of id command is passed to base64 command. Decoding this text looks as follows.
uid=33(www-data) gid=33(www-data) groups=33(www-data)$
As you can notice, the encoded text is the output of the id command passed to the application.
When applications receive user input, if it is expected to be data the applications must treat it as data. If this user supplied data is appended to existing commands by the application, without sanitizing it; it will lead to vulnerabilities like command injection as the data is treated as code. The data must be treated as data and it must not be treated as code.
This article has provided an overview of why command injection vulnerabilities occur. While some applications become vulnerable to command injection due to poor design choices, some applications become vulnerable due to insecure coding practices. When developers expect applications to process user supplied data, care must be taken and appropriate validation must take place to prevent injection class of vulnerabilities.