Noté un comentario muy desviado aquí: enlace
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');");
Intenté omitir el código y conducir a una ejecución de entrada de usuario malintencionada con eval
, pero no pude. Me pregunto por qué se bajó de votación.
Como puede ver si los corchetes no coinciden, no agrega el 'if(0){' . $code . '}
y ejecuta la entrada del usuario tal cual con corchetes que no coinciden, lo que generará una excepción y no se ejecutará realmente.
Si los corchetes son una coincidencia, llama a eval
, pero debido a que está dentro de if {0}
"sandbox", no hace nada. ¿Cómo puede alguien pasar por alto esto?
Sé que eval es inseguro, pero quiero saber cuál es el truco aquí. ¿Cómo puede pasar por alto la seguridad de if (0) y las llaves verifique el código anterior?
Intenté agregar // {para que desequilibre las llaves y no agregue if (0) y llame a eval, pero token_get_all lo arruina.