1

OWASP recommends as defense against command injection to escape all special characters (if a whitelist approach cannot be used).

I wrote a quick PHP script doing this:

$input = $_GET['x'];
$dangerous = array("{", "}", "", "(", ")", "<", ">", "&", "*", "|", "=", "?", ";", "[", "]", "$", "–", "~", "!", ".", "%", "/", ":", "+", "'");

$input = str_replace("\\","\\\\",$input);
foreach ($dangerous as $char) {
    $input = str_replace($char,"\\$char",$input);
}

echo  passthru("echo '$input'");
echo "<br><br>executed: " . $input ;

However, if I use ' as input, it will result in an error (Unterminated quoted string).

I wasn't able to bypass the escaping of these characters, but it doesn't seem ideal that an attacker can generate a bash error because of invalid syntax.

Is there a way to bypass the escaping of these special characters?

I know that using a whitelist or existing mechanisms like escapeshellcmd would be recommended. I am more interested in the general idea of bypassing the escaping of special characters.

  • 2
    Backslash escaping doesn't work between single quotes. That is why \' still terminates the string and you get an error. – Sjoerd Dec 13 '18 at 12:23
  • @Sjoerd Right. But is this behaviour exploitable? – tim Dec 13 '18 at 13:39
2

I came up with a bypass.

As @Sjoerd mentioned, backslash escapes don't work in single quoted strings, so it's possible to get out of the single quoted string.

Your list of 'dangerous' characters does not include backticks, or hashes; which allows a payload such as this one to work:

' `hostname` #

Or urlencoded:

%27%20%60hostname%60%20%23

The single quote becomes \' (which is treated as a regular quote, and '\' becomes the first argument to echo), the command in backticks is executed with the command output passed to echo. The hash is treated as a comment and causes the shell to ignore the trailing single quote, avoiding a syntax error.

  • Damn, I removed backticks in my local test because I didn't want to bother checking how I can get the PHP code to work with them, and forgot about it before posting the question (+1 for noticing). I'm fine with the hash sign missing from the filter. Would there also be a bypass if I hadn't screwed up the PHP code (ie with escaped backticks)? – tim Dec 13 '18 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.