I noticed a heavily downvoted comment in here: http://php.net/manual/en/function.php-check-syntax.php
function eval_syntax($code)
{
$braces = 0;
$inString = 0;
// We need to know if braces are correctly balanced.
// This is not trivial due to variable interpolation
// which occurs in heredoc, backticked and double quoted strings
foreach (token_get_all('<?php ' . $code) as $token)
{
if (is_array($token))
{
switch ($token[0])
{
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case T_START_HEREDOC: ++$inString; break;
case T_END_HEREDOC: --$inString; break;
}
}
else if ($inString & 1)
{
switch ($token)
{
case '`':
case '"': --$inString; break;
}
}
else
{
switch ($token)
{
case '`':
case '"': ++$inString; break;
case '{': ++$braces; break;
case '}':
if ($inString) --$inString;
else
{
--$braces;
if ($braces < 0) return false;
}
break;
}
}
}
// If $braces is not zero, then we are sure that $code is broken.
// We run it anyway in order to catch the error message and line number.
// Else, if $braces are correctly balanced, then we can safely put
// $code in a dead code sandbox to prevent its execution.
// Note that without this sandbox, a function or class declaration inside
// $code could throw a "Cannot redeclare" fatal error.
echo "Braces: ".$braces."\r\n";
$braces || $code = "if(0){{$code}\n}";
if (false === eval($code)) {}
}
eval_syntax("file_put_contents('/home/yourname/Desktop/done.txt', 'OVERWRITTEN');");
I tried to bypass the code and lead to malicious user-input execution with eval
, but I couldn't. I wonder why it got downvoted.
As you can see if curly brackets are not matching, it doesn't add the 'if(0){' . $code . '}
and executes the user input as-is with mismatching curly brackets which will throw exception and won't really run.
If curly brackets are a match, it calls eval
, but since its inside if {0}
"sandbox", it doesn't do anything. How can someone bypass this?
I know eval is insecure, but I want to know what's the trick here. How can you bypass security of if (0) and braces check in the code above?
I tried to add // { so it will imbalance the curly brackets and it won't add the if (0) and call eval, but token_get_all ruins that.