Command injection occurs when an application constructs system commands using untrusted user input without proper sanitization or validation. An attacker can…
Command injection occurs when an application constructs system commands using untrusted user input without proper sanitization or validation. An attacker can inject shell metacharacters or additional commands into the input, causing the application to execute unintended operations with the privileges of the web server or application process. This is a critical vulnerability that can lead to complete system compromise.
02How It Happens
Applications sometimes need to invoke system commands—to resize images, compress files, send emails, or interact with external tools. When developers build these commands by concatenating user input directly into a command string, they create an opening for injection. Shell interpreters like bash or cmd.exe treat certain characters (;, |, &, backticks, $()) as special operators that chain or redirect commands. If an attacker controls part of the input, they can insert these metacharacters to break out of the intended command and execute arbitrary code. The vulnerability is especially severe when the application runs with elevated privileges or in a context where it can access sensitive files or network resources.
03Real-World Impact
Successful command injection allows an attacker to execute arbitrary system commands with the privileges of the web server process. This can result in unauthorized file access, data theft, malware installation, lateral movement within a network, or complete server compromise. In shared hosting environments, an attacker might escalate from one compromised account to others. The impact is not limited to the application itself—the attacker gains a foothold to attack other systems on the same network or to use the server as a launching point for further attacks.
Why it's vulnerable: The shell=True parameter causes the string to be interpreted by a shell, and the user input is not validated or escaped. An attacker can inject shell metacharacters like ; rm -rf / or | cat /etc/passwd to execute arbitrary commands.
Fixed pattern
import subprocess
import sys
import os
def resize_image(filename):
user_input = sys.argv[1]
# Validate input: allow only alphanumeric, dots, and hyphens
if not all(c.isalnum() or c in '.-_' for c in user_input):
raise ValueError("Invalid filename")
# Use list form with shell=False to avoid shell interpretation
command = ["convert", user_input, "-resize", "100x100", "output.jpg"]
subprocess.run(command, shell=False, check=True)
resize_image(sys.argv[1])
Why it's vulnerable: The shell_exec() function passes the string to a shell for interpretation. An attacker can inject commands like ; whoami or | cat /etc/passwd by manipulating the file parameter.
Fixed pattern
<?php
$filename = $_GET['file'];
// Validate input: allow only safe characters
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) {
die("Invalid filename");
}
// Use escapeshellarg() to safely escape the argument
$safe_filename = escapeshellarg($filename);
$output = shell_exec("identify " . $safe_filename);
echo $output;
?>
05Prevention Checklist
Avoid shell execution when possible. Use language-native libraries or APIs instead of invoking system commands (e.g., use image processing libraries rather than calling convert or ImageMagick via shell).
Never pass user input directly to shell functions. If you must execute a command, use parameterized/list-based APIs (subprocess.run() with shell=False, proc_open() with an array, etc.) that do not invoke a shell interpreter.
Validate and allowlist input. Restrict user input to a known-safe set of characters or values (e.g., filenames matching [a-zA-Z0-9._-]+). Reject anything that doesn't match.
Use escapeshellarg() or equivalent as a last resort. If you cannot avoid shell execution, use language-provided escaping functions, but treat this as a secondary defense, not a primary one.
Run the application with minimal privileges. Configure the web server and application process to run under a dedicated, unprivileged user account with no access to sensitive system files or commands.
Log and monitor command execution. Record which commands are being executed and by whom; unusual patterns may indicate an attack in progress.
06Signs You May Already Be Affected
Check your application logs for unusual shell commands, unexpected process spawning, or error messages from system utilities being called with malformed arguments. Look for suspicious entries in web server access logs containing shell metacharacters (;, |, &, backticks) in query strings or POST parameters. If you discover unexpected files in your web root or unexpected cron jobs, or if system administrators report unusual network traffic or process activity originating from your application server, investigate whether command injection has occurred.