What are Command Injection vulnerabilities?
How command injection vulnerabilities allow attackers to take over your machine, and how you can prevent these vulnerabilities.
Command injection vulnerabilities are probably one of the most dangerous vulnerabilities that can happen in an application.
Command injection vulnerabilities, or OS command injection vulnerabilities, happen when an application allows user input to be confused with system commands. This happens when user input is concatenated directly into a system command without proper precautions. Let’s understand them with an example!
Calling system commands in code
Let’s say that your web application has a functionality that allows a user to download a webpage through your site. To achieve this functionality, you use Python to execute the system command wget to download the webpage. This is what your code looks like:
import os
def download(url):
os.system("wget -O- {}".format(url))
display(download(user_input.url))
You first define a function called download, which calls wget to download the contents from the URL passed in. It then calls download on user-supplied input and displays the results.
If a user submits the following request, the application would download Google’s home page and display it back to the user:
GET /download?url=google.com
Host: example.com
How command injections happen
On the Linux command line, the semicolon (;) character separates
individual commands. And since the user input here is passed into a system command directly, an attacker can execute arbitrary commands after the wget command by submitting whatever command they want after a semicolon.
For example, what would happen if a malicious user submitted this request?
GET /download?url=google.com;ls
Host: example.com
This request would cause the application to execute both wget -O- google.com and ls, which outputs the contents of the current directory. Since the application will then display the results of the command back to the user, the malicious user would be able to read the output of the ls command as well.
Similarly, the attacker can read sensitive files with this vulnerability too:
GET /download?url=google.com;cat /etc/shadow
Host: example.com
/etc/shadow is a file on Unix systems that stores hashed user passwords.
The attacker would be able to execute any system commands that the user running the web application has permission to execute. For instance, they might be able to read sensitive files, reach and exploit other machines on the local network, or modify files on the server.
How can I prevent command injections?
So how can you prevent command injection vulnerabilities in code? To prevent command injections, you should avoid inserting user input directly into system commands.
The first alternative strategy you can use is to use the programming language’s system APIs instead of calling system() directly. Most programming languages have built-in functions that allow you to run common system commands without risking command injection. For instance, PHP has a function named mkdir(DIRECTORY_NAME). You can use it to create new directories instead of calling system("mkdir DIRECTORY_NAME").
If you have to insert user input into system commands, implement strong input validation before passing user input into a system command. You can use an allowlist of strings or characters to specify the values that are allowed and reject all other user input that does not conform to that format. For instance, if you want to allow users to read a subset of system files using a system command, you can create a list of allowed file names and reject all other input. You can also use regular expressions to limit user input to a specific subset of characters to prevent users from submitting special characters that can allow them to manipulate system commands. For instance, this regex string will limit the user input to alphanumeric characters, and limit the user input to 15 characters: ^[A-Za-z0–9]{1,15}$.
Defense-in-depth strategies
Finally, there are also defense-in-depth strategies that can help you minimize the risk of command injections. First, you can deploy a WAF (web application firewall) to help filter out suspicious user input.
You should also run your application with only the privileges it needs to complete its tasks. For example, when an application requires only read access to a file, it shouldn’t be granted any writing or execution permissions. This is called the “principle of least privilege”. This practice will lower your risk of system compromise during an attack because attackers won’t be able to gain access to sensitive files and operations even if they gain command injection on the application.
How can I find command injections in my code?
Command injection vulnerabilities have specific signatures in code, such as passing user-supplied or user-tainted input into dangerous system commands. That’s why code analysis or static analysis is the most efficient way of uncovering command injections in your applications. ShiftLeft’s static analysis tool NG-SAST can find the command injection bugs in your code and help you fix them. Learn more by visiting us here.
Thanks for reading! What is the most challenging part of developing secure software for you? I’d love to know. Feel free to connect on Twitter @vickieli7.
What are Command Injection vulnerabilities? was originally published in ShiftLeft Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.
*** This is a Security Bloggers Network syndicated blog from ShiftLeft Blog - Medium authored by Vickie Li. Read the original post at: https://blog.shiftleft.io/what-are-command-injection-vulnerabilities-d3127afd78c4?source=rss----86a4f941c7da---4