Command Injections Through Parameter Expansion
The following is an example of using shell parameter expansion to overcome the limitation of using spaces in a command injection vulnerability found in a web application parameter.
A simple test to try if you suspect a parameter is being passed to a shell script, binary or executable on the system would be to add ;whoami
after the final parameter, or test for a blind injection by adding ;ping -c <your ip>
. So for example
http://10.161.23.15?zoom=5&direction=up;whoami
The semicolon in Bash is used to signify the end of one command and the beginning of another. We need to include that first to end whatever command the application was attempting to run and begin executing the command we are trying to inject. If you wanted to chain two commands together you could use ;whoami&&id
. I mention that because the &&
will be an important part of getting our command injection to work.
We can see in Burp Repeater’s Response pane that the output that our command was executed and displayed just below the text ‘Camera Adjusted’. whoami
returned daemon
and id
returned uid=2(daemon), gid=2(daemon), group=2(daemon), 1(bin), 4(adm)
.
But when trying to execute a command with a space in it
http://10.161.23.15?zoom=5&direction=up;cat%20/etc/passwd
we get don’t get any output from our command.
Keep in mind that entering a space to any part of a url in your browser’s url bar will cause that space to be hex encoded automatically before it is sent to the server. However in Burp you can send the request directly to the server as an unencoded space. Most of the time this will cause a server error, but sometimes not, so it’s worth trying. In this instance sending the command with an unencoded space caused the web application to return a 400 bad request error, so the parameters we send to the server need to be url encoded.
We can assume that the hex encoded space (represented by the value %20
) is causing the command to fail because the hex encoding is being passed directly to the system shell, and since cat%20/etc/passwd
is not valid syntax in Bash the command fails.
So at this point we have command injection but we’re limited to only using single commands without any spaces, which isn’t all that useful. A possible way around this could be to use shell parameter expansion
to convert cat /etc/passwd
into a string that doesn’t throw an error when tacked onto the end of the url parameter and that also executes when passed to the Bash shell.
To see this working directly in your own linux terminal, paste CMD=$'\x20/etc/passwd'&&cat$CMD
into Bash (this failed for me in zsh so make sure you’re using Bash), and it will execute cat /etc/passwd
successfully. To break down the parts of the entire command, first we create a variable CMD
and assign it the value $'\x20/etc/passwd'
, which will add the string /etc/password
preceded by a space to the variable CMD
. Second, the &&
tells bash to execute the next command if the previous command completed successfully. This is necessary because the syntax cat$'\x20/etc/passwd'
is also not valid. Finally, cat$CMD
will transform into cat /etc/passwd
when executed in the system shell.
We can see from our output below that our command was successful
Here’s an article with examples and use cases for parameter expansion at gnu.org. All of the examples on that site use braces instead of quotes, but quotes are also valid in place of braces.