7

The dangers of PHP eval()

Yup. "Scary, you better make use of include instead" — I read all the time everywhere. I want to hear good case scenarios and feel safe with it.

I use the eval() method as a good resource to build custom website modules written in PHP which are stored and retrieved back from a database. I ENSURED IS SAFE AND CAN ONLY BE ALTERED THROUGH PRIVILEGED USERS. THERE. I SAID IT. You could as well develop a malicious module and share it to be used on the same application, but this application is just for my use at the moment so I don't wanna worry more or I'll become bald.

I had to take out my fear and confront it in front of you guys. If i had to count every single time somebody mentions on Stack Overflow or the comments over PHP documentation about the dangers of using eval I'd quit already.

Tell me if I'm wrong: in a safe environment and trustworthy piece of code is it OK to execute eval('?>'.$pieceOfCode); ... Right?

The reason I store code on the database is because I create/edit modules on the web editor itself.

I use my own coded layers to authenticate a privileged user: A single way to grant access to admin functions through a unique authentication tunnel granting so privileged user to access the editor or send API requests, custom htaccess rules to protect all filesystem behind the domain root path, a custom URI controller + SSL. All this should do the trick to safely use the damn eval(), is that right?!

Unless malicious code is found on the code stored prior to its evaluation.

But FFS, in such scenario, why not better fuck up the framework filesystem instead? Is one password closer than the database.

I will need therapy after this. I swear.

If 'eval is evil' (as it appears in the suggested tags for this post) how can we ensure that third party code is ever trustworthy without even looking at it? This happens already with chrome extensions, or even phone apps a long time after reaching to millions of devices.

Comments
  • 0
    The specific case scenario is this: This code is ensured to ONLY be called through the admin section, and the admin section ONLY loads if the user has privileges. Is this, then, a legit use of eval()?

    PD: Apologies for the very small picture!
  • 7
    Ok since your using eval() despite the warning labels, I'll make it simple.

    Eval is a terrible idea at best to utilise, raw code from an external resource means there's an attack vector to hijack or even break your code that you have no oversight over.

    This is also undocumented and completely untestable behaviour for the project, as you are injecting code that doesn't exist in the code base naturally.

    How does it work with include() then?
    Because your codebase knows about it, you can write tests to check it's functioning and you can follow error logs to workout where something went wrong.
    Also, performance would be a bitch at scale, querying for code... then executing it... this is all occurring at runtime and can become unpredictable.

    Do you even have code testing?

    There's also the issue of, who's administering the code being added to the DB?
    Do they know it works?
    How do they know?

    Debug logs would be an absolute bitch to track things aswell.

    Unexpected "}" on line 8474737 in someFile.php

    But yet... that file only has 300 lines.

    I get it, eval() can be of use, but there's a very limited scope I would actually use it in, since it can be hijacked without warning.

    eval($_post['foo']);

    for example is literally handing your site and anything else it has access to over to who ever knows about it.

    As for your last comment about 3rd party code.
    In php, you look at it.

    Chrome extensions, you rely on
    Google to review it and say it's not trusted and remove it, although I think this should be the other way like they do with Mobile Apps.
  • 4
    @C0D4 Im taking your very welcome feedback and I am going to find a workaround to completely remove all eval() calls. I will instead store the modules in the filesystem. Its most true that its a bitch to debug... And makes the code feel vulnerable, even if its being safely executed by admins only.

    Thanks a ton!
  • 3
    The ONLY time I have used eval was when I was running a filtering algorithm against a data set of unknown length...

    Which ALSO had to consider and / or relations to each entry in a combinative filter.

    What I ended up doing was pass/failing each parameter and then building a sort of matrix of true false statements that in simple terms might look like: ((true and false) and false) or true)... just for example, the length of the filter was unlimited, so depending what the user did, this statement could get very long and very nested.

    Anyway, I then ran that "truthiness statement" through eval to get a final answer as to wether that cell of the data matched all filter criteria or not.

    As for passing code from a database into eval? That is the exact reason everybody gives eval a bad name. Just no. If i could spray you with a spray bottle I would.
  • 1
    If I understand you correctly the security is in the code not the DB (user/grants) itself. If there is ever s tiny mistake in all of your public facing code where a SQL injection can happen you also give the attacker random code execution! This is why it's unsafe to eval().
    Using includes does not make it that much safer!!! As soon as the PHP interpreter can write code it can also execute you have the same issue. If a file upload/write can happen to one of your code locations the attacker can write arbitrary code.
    The advantage of using includes is performance though and generally there are more issues with SQL breaches if your webserver is configured correctly.

    I've not looked into this problem yet but perhaps there is a way to run the code sandboxed like the live online php coding tools do. The other way is reducing attack surface by having a separate surface set up with different user (sql user or os/storage user) that gathers and writes the code. That is the only responsibility of that service.
  • 1
    @hjk101 I forgot one. You mentioned apps and browser extensions. They have there code submitters authentication verified with code signing. This is also something you could implement. The coffee had to be signed and will be validated every run (freaking slow but only way to guarantee its the same unaltered code)
  • 2
    @HiFiWiFiSciFi I've used it in similar fashion. I build code based on various input and than executed it with eval. Note that the input itself was never executed only used to build the code.
    This was a long time ago and there probably was a better way to do it but it worked.
  • 0
    global variables, switch-statements, all these nested if-statements, fucking arrays everywhere, fucking eval... And let me guess, your code-coverage is 0%?

    Sorry to be so blunt, but there is A LOT to improve.

    The way to start might be to add a global exeption-handler in the index.php + cli.php with a generic error message + log-reference and logging. Then you check for specific errors "if is_null($example)" and throw an exception. This will clear up your nested if-statements: if you have an error, show the fucking error.

    I highly recommend getting familiar with so called "code smells" (and how to remove them): https://refactoring.guru/refactorin...
  • 0
    not bad)
  • 1
    @SuspiciousBug I do have error handlers and test my code vigorously in detail. What you are looking in the picture is a custom action block from a module and not part of the mainline application. The switch statement is performing small specific tasks from commands on $_GET and data from $_POST. In any case, I take refactoring in general a key aspect in programming and I FIND YOUR COMMENT OFFENSIVE--just kidding. But I try my best in keeping it as sorted and coherent as I can. Can I do better? I hope so. And thanks for the link as a good reminder.
  • 0
    @hjk101 I realized shortly after my first comment that code is anyways getting in, and therefore somewhat an isolated environment to execute this scripts could be mandatory.

    Think of a Wordpress plugin, they get uploaded as zip but contain implicit php code and custom classes/calls... I will research on how to safely do so.
Add Comment