1

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 to maliciously execute user-input, 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 with mismatching curly brackets which will throw exception and won't really run.

If curly brackets are a match, it calls the eval, but its inside a if {0} "sandbox". 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?

You can try directly the code from php.net or my minified/edited version above. Point is proving that this code is not secure and user an execute arbitrary PHP Code

JohnDoes
  • 19
  • 3
  • check this answer about eval: https://stackoverflow.com/a/951868/3541922 – MikeVelazco Jan 24 '18 at 00:50
  • @MikeVelazco I know eval is completely insecure, but what's the trick here? How can someone bypass the security check in the code above? – JohnDoes Jan 24 '18 at 00:52
  • It does not check the syntax either, it only checks broken braces, so it's useless. – Lawrence Cherone Jan 24 '18 at 01:13
  • @LawrenceCherone You may have overlooked the `eval()` at the end. –  Jan 24 '18 at 01:16
  • @duskwuff nope, im testing it and im always getting Braces: 0 for valid and invalid code. Try it: `eval_syntax("if(){}");` shows as valid but its obviously not. – Lawrence Cherone Jan 24 '18 at 01:20
  • Is the point of the function not to validate its working php code but not execute it :/ – Lawrence Cherone Jan 24 '18 at 01:23
  • the point of the code is to validate but not execute the PHP code, but I want to bypass its security and execute user input directly with eval – JohnDoes Jan 24 '18 at 01:24
  • @LawrenceCherone Get the original code from PHP.net site comment and see if you can break it's jail and execute user input directly with the eval – JohnDoes Jan 24 '18 at 01:25
  • You cant as `if (0){}` will never execute. But again its useless as it does not check all syntax errors lol – Lawrence Cherone Jan 24 '18 at 01:25
  • being useless is true, but I wan't to know if someone can somehow bypass it and execute arbitrary PHP codes. I tried to add " // { " as to imbalance the curly brackets so it won't add the if (0) check and call eval directly, but get_tokens call ruins it. Trying to find a way to prove its inscure – JohnDoes Jan 24 '18 at 01:28
  • 1
    Since its using the same AST parser as php does, any tricking with the comments will fail. I've checked all possible {-s in the code, but couldn't spot any that was missed out. Ref: https://github.com/php/php-src/blob/a7fe2570d3ce6915d4ea85c62c0f880ddc225ba7/Zend/zend_language_parser.y – lintabá Jan 24 '18 at 01:36
  • @lintabá Exactly! I tried lots of methods to bypass it to execute an arbitrary user-input. So far nothing... – JohnDoes Jan 24 '18 at 01:37
  • The rule of thumb is slate the hell out of `eval()` even if its used safely, like above because of `if (0) {}` that's the protection, remove that and it will be a different story.. people love to jump on the evil/eval bandwagon (its cheap to downvote on php.net), the same people who see a SQL injection and love to throw bobby drop tables comical comment, when they know you cant drop a table without using a multi query api. i've built many projects which have used eval without problems, even netflix use a "script engine" which eventually hits an eval mechanism of sorts lol.. – Lawrence Cherone Jan 24 '18 at 01:37
  • @JohnDoes I've edited my comment (damn auto-submit by enter..) – lintabá Jan 24 '18 at 01:38
  • I didn't write the code, I'm trying to prove its insecure, unless I get code execution, I can't make my point – JohnDoes Jan 24 '18 at 01:38
  • @lintabá good thinking... do you see any other way of bypassing the code? – JohnDoes Jan 24 '18 at 01:40
  • @JohnDoes I've tried the function declaration too, but that works only in js. So unfortunatelly nothing yet, otherwise I'd have sent an answer. But a negative result is also a result :) – lintabá Jan 24 '18 at 01:50
  • @lintabá Thanks for sharing the update. I'm testing as well. Lets see who n find the answer first :) – JohnDoes Jan 24 '18 at 01:59
  • I'm voting to close this question as off-topic because it was cross posted at https://security.stackexchange.com/questions/178276/php-eval-code-sandbox-break – symcbean Jun 20 '18 at 13:29

0 Answers0