Preventing Command Injection
Introduction
Welcome to the final lesson of the "A03: Injection" course! In previous lessons, we've explored various injection vulnerabilities, such as SQL and XSS injections, and their impact on web application security. In this lesson, we'll focus on command injection, a critical vulnerability that occurs when user input is improperly handled in command execution, particularly in file processing.
Understanding and mitigating command injection is essential to prevent unauthorized command execution and potential system compromise. Let's dive in! 🚀
Understanding Command Injection
Command injection (also known as OS injection) is a type of security vulnerability that occurs when an application passes unsafe, user-supplied data to a system shell. This allows an attacker to execute arbitrary operating system (OS) commands on the server. Unlike other injection attacks that target specific components (like SQL injection targeting a database), command injection targets the underlying host operating system, making it one of the most dangerous vulnerabilities.
Developers often use system commands to leverage powerful and efficient utilities built into the OS, such as file manipulation tools (ls, wc, find), network utilities (curl, ping), or other custom binaries. The vulnerability arises when user input is concatenated into a command string that is then executed by a shell. The shell interprets special characters in the user input not as simple text, but as instructions to chain, modify, or execute new commands.
Suppose that in our pastebin application, we have an endpoint for getting file statistics (like word count) of uploaded files. This endpoint uses the system's wc command to count words in files. Without proper security measures, an attacker could manipulate the filename input to run commands far beyond the intended wc utility.
Now that we understand the basics of command injection and have context for our example, let's look at some vulnerable code to see how this attack works in practice.
The Vulnerable Code
Let's examine a code snippet that demonstrates a vulnerable endpoint. This example uses Python's subprocess module with FastAPI, a common way to interact with the system shell. The vulnerability is introduced when user input is directly formatted into a command string and executed with shell=True.
In this code, the file_stats function takes a filename from a POST request. The core of the vulnerability lies in these two lines:
command = f"wc {filename}": Thefilenameprovided by the user is directly embedded into the command string. There is no sanitization or validation to check for malicious characters.subprocess.run(command, shell=True, ...): Theshell=Trueargument is critical. It tellssubprocessto pass the entirecommandstring to the system's default shell for execution. The shell then parses this string, and if it contains command separators (like;), it will execute the commands sequentially.
This combination creates a perfect storm for command injection. Let's see how an attacker might exploit this.
