Web Applications Security - What Is Command Line Injection?
Image source from Acunetix

Web Applications Security - What Is Command Line Injection?

Introduction

In the previous article, we talked about SQL injection and demonstrated its damage and harmful effects. In this article, we will talk about another vulnerability that's less common but more destructive, the command line injection.

Command line injection is a type of security vulnerability that occurs when an attacker inserts malicious commands into a command-line interface (CLI) of a software application. The injected commands can then be executed with the privileges of the application or the user running it, potentially allowing the attacker to gain unauthorized access or control of the system.


How Does An Application Become Vulnerable?

The scenario is really simple. In PHP, the function shell_exec() can be used to execute a command line on the operating system's shell. For example, let's assume that we have a form where a user can enter a URL, and our server-side code will take that URL and return its content. This operation is done using the curl command as follows:

$url = $_GET["url"]; // acquire the URL
echo shell_exec("curl $url"); // execute the command and print its output        

For example, the user enters https://example.com and submits the form, and the following result is shown on the screen:

No alt text provided for this image

Until now, everything looks fine. However, let's assume the worse: a user tries and enters (https://example.com/ && sleep 100). In this case, the OS shell will execute the following command:

curl https://example.com && sleep 100        

This command will retrieve the content of the URL and then pause for 100 seconds. PHP will wait until shell_exec() returns before resuming execution. Until now, there's nothing much serious happening here. However, let's assume that our user used an input like (https://example.com/ && rm -rf app). In this case, the OS shell will run the following command:

curl https://example.com && rm -rf app        

Essentially, this command performs two actions: firstly, it retrieves the contents of a URL, and secondly, it deletes the "app" folder in the current directory. The second action has the potential to cause severe damage to the system and should be avoided.


What Should Be Done About This?

There are several methods that can be effective in reducing the likelihood of such attacks. Let's explore some of these methods.

Don't Call OS Commands Directly

The primary cause of an application's vulnerability to command-line injection is the unsafe practice of directly concatenating parameters with the command, making it risky to execute. To prevent this vulnerability and avoid potential headaches, it is advisable to utilize built-in functions that can perform the same task instead of writing such commands directly.

For example, in PHP:

  • You can use the mkdir() function to create a directory, instead of executing the mkdir command manually
  • You can use the curl_*() functions instead of executing the curl command manually.

And so on. Almost every command has an equivalent function in PHP that encapsulates it. These functions work in a safe way that prevents changing the intent of the command.

Escape Values Passed To The Command

If you cannot find a function that encapsulates the desired command, and you don't have any solutions left, you still can do it in a safe way.

Thank God, in PHP we have a function called escapeshellarg(). This function takes the input and escapes it in a safe manner that makes the command less dangerous to execute. For example:

$url = $_GET["url"]; // acquire the URL
$clean_url = escapeshellarg($url); // sanitize the URL
echo shell_exec("curl $clean_url");        

Now, if the user enters (https://example.com/ && rm -rf test-folder) as a URL, then the escape function will escape it, and the final command to be executed will look like this:

curl 'https://example.com/ && rm -rf test-folder'        

And curl will reply with an error regarding the format of the URL. As you can see, the whole user input part has been interpreted as a parameter to be passed to the command.

Input Validation & Whitelisting

Regarding the arguments of command, there should be a whitelisting policy such that the arguments and their corresponding values are explicitly defined or validated using a regular expression approach such that:

  • Metacharacters like: & | ; $ > < ` \ ! ' " ( ) are not part of the regex
  • The length should be limited (e.g. minimum length is 3 characters and maximum length is 10 characters)

This topic will get the focus it deserves in a future article.

The Concept Of Least Privilege

Each process runs on behalf of a specific user and has its own set of privileges. For example, the www-data or nginx users which are used by several types of web servers may not need to have access to files inside the directory /usr/local/bin, and they also may not need to have access that allows them to control system services.

Instead, a process should get the minimum required amount of privileges to run correctly. Don't give more privileges than needed to a process.


Laravel And Command Line Injection

Luckily, Laravel framework provides the Process facade which is a wrapper around the process component in Symfony. The facade is available under the Illuminate\Support\Facades namespace.

This addition is very powerful, it provides many options to control the execution of a process plus the ability to run asynchronous and run processes. However, what matters for us here is the run() method. This method takes a single parameter which can be either a string or an array.

  • If it's a string, the method assumes it's a command and passes it to the OS shell for execution.
  • If it's an array, the method assumes that the first element is the name of the command to be executed, and the rest of the elements are the arguments that should be passed to the command. These arguments are passed in a safe way.

Let's see our curl example once again written using this feature:

use Illuminate\Support\Facades\Process;

$url     = $request->url;    
$process = Process::run(["curl", $url]);    
$process->output();    
$process->errorOutput();        

If the URL passed was invalid or malformed, curl will reply with the same error message we have previously seen.


Conclusion

In conclusion, command line injection is a serious security vulnerability that can allow attackers to execute arbitrary commands on a system. It can be prevented by properly validating and sanitizing all user input that is passed to a?command line interpreter, and by using safer alternatives to executing commands whenever possible. If you suspect that your system may be vulnerable to?command line injection, it is important to take immediate action to mitigate the risk and implement additional security measures to prevent similar vulnerabilities from occurring in the future. By following best practices for?secure coding?and regularly updating and monitoring your system, you can help protect yourself and your users from the risks of command line injection and other security threats.

I love your articles it always has something new to learn from.

要查看或添加评论,请登录

Eyad Bereh的更多文章

社区洞察

其他会员也浏览了