6

I'm trying to learn more about PHP eval() exploitation and I came across this scenario:

<?php

$test = array();
$test[0] = "command0 ";
$test[1] = $_GET["cmd1"];
$test[2] = "command2 ";
$test[3] = "command3 ";

$params = "";
for ($i = 0; $i < count($test); $i++) {
        $params .= "\$test[$i]";
}

echo $params;
echo "<br>";

$cmd = "echo \"" . $params . "\";";
echo $cmd;
echo "<br>";

eval($cmd);
?>

I've tried to inject several combinations of double-quotes and backslashes into the $_GET parameter but have had no luck breaking out of the $cmd string.

Beyond the XSS bug, is this code snippet vulnerable? Can this be abused for PHP code injection?

  • I think you have setup a bit of complexity for teaching yourself eval() exploitation. I did notice that when you define the strings in $test[x] for {x=0,2,3} there is a space afterwards but when you set $_GET["cmd1"] there is no string afterwards. – Eric G Jan 10 '18 at 3:53
  • It was just a quick and dirty abstraction of some source code I was reviewing. – Robleh Jan 10 '18 at 23:35
5

No, this is not vulnerable to PHP code injection.

The string passed to eval() is simply not user-controlled. There is no path from the source $_GET["cmd1"] to the sink eval():

  • The argument to eval() is $cmd.
  • $cmd is assembled from a fixed string and $params.
  • $params is accumulated from a fixed string and $i.
  • $i is an iteration variable that depends on the (fixed) length of the array $text.

That said, passing a generated array through eval is certainly not good style and you're obviously not sanitizing output which makes the code vulnerable to XSS.

  • Makes sense thank you, +1 for mentioning source to sink – Robleh Jan 10 '18 at 23:40
1

The code you are evaluating here is actually completely fixed, so PHP code injection is not possible here.

The code that gets evaled is always:

echo "$test[0]$test[1]$test[2]$test[3]";

It references those variables as string data, which is safe (except against XSS).

  • Did you test this? e.g., ?cmd1=TEST I get command0 TESTcommand2 command3 but If I do ?cmd1=<?php TEST ?> the output is command0 command2 command3. I have tried some PHP scripts, instead of TEST like phpinfo(); it doesn't show me the output, but it doesn't show me the raw text from ?cmd1= – Eric G Jan 10 '18 at 4:11
  • @EricG That's because it's vulnerable to XSS and you don't see the pseudo-tag <?php ...?> printed. It becomes clearer if you inspect the source code. – Arminius Jan 10 '18 at 4:12
  • Yep i was testing in the browser and just noticed now the browser escaped it inside html comments. – Eric G Jan 10 '18 at 4:17

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.