Is Eval a good guy or a bad guy?

Asked

Viewed 1,642 times

40

They talk a lot about eval, but sometimes I wonder if he really is the problem or is the person sitting in front of the computer (the supposed programmer).

My whole life (in programming) I have heard criticism, jokes, jokes about this function eval, but the curious thing is that, even those who mock, end up using libraries that use it internally, without knowing.

An example of this is Laravel 3, that in the system of views, uses eval.

Example (I removed the comments from the original code):

    public function get()
    {
        $__data = $this->data();

        $__contents = $this->load();

        ob_start() and extract($__data, EXTR_SKIP);

        try
        {
            eval('?>'.$__contents);
        }
        catch (\Exception $e)
        {
            ob_get_clean(); throw $e;
        }
        $content = ob_get_clean();

        if (Event::listeners('view.filter'))
        {
            return Event::first('view.filter', array($content, $this->path));
        }

        return $content;
    }

GITHUB - view.php - line 385

True, it is already discontinued, but it is not in a distant era (its version is for PHP 5.3). But it would come as no surprise if one of the critics of eval had using that framework unaware of this information.

And yet I give another example, that many programmers also use, but without knowing it. The Superclosure that is used in Laravel 4 and Laravel 5. This library aims to provide a possibility to serialize closures in PHP, since natively closures PHP does not support serialization. This library becomes useful for those who need to use queue systems, such as Beanstalkd, where the information passed is usually a string, and therefore PHP data needs to be serialized.

Example:

    /**
     * Reconstruct a closure.
     *
     * HERE BE DRAGONS!
     *
     * The infamous `eval()` is used in this method, along with the error
     * suppression operator, and variable variables (i.e., double dollar signs) to
     * perform the unserialization logic. I'm sorry, world!
     *
     * This is also done inside a plain function instead of a method so that the
     * binding and scope of the closure are null.
     *
     * @param array $__data Unserialized closure data.
     *
     * @return Closure|null
     * @internal
     */
    function __reconstruct_closure(array $__data)
    {
        // Simulate the original context the closure was created in.
        foreach ($__data['context'] as $__var_name => &$__value) {
            if ($__value instanceof SerializableClosure) {
                // Unbox any SerializableClosures in the context.
                $__value = $__value->getClosure();
            } elseif ($__value === Serializer::RECURSION) {
                // Track recursive references (there should only be one).
                $__recursive_reference = $__var_name;
            }
            // Import the variable into this scope.
            ${$__var_name} = $__value;
        }
        // Evaluate the code to recreate the closure.
        try {
            if (isset($__recursive_reference)) {
                // Special handling for recursive closures.
                @eval("\${$__recursive_reference} = {$__data['code']};");
                $__closure = ${$__recursive_reference};
            } else {
                @eval("\$__closure = {$__data['code']};");
            }
        } catch (\ParseError $e) {
            // Discard the parse error.
        }
        return isset($__closure) ? $__closure : null;
    }

Github - Serializableclosure.php - line 187.

Thinking about the usefulness of the classes of the libraries presented above, remembering that they are only two examples, but there must be other cases, I wondered if I should still speak bad of eval or simply make an analysis and evaluate when it is good or bad to use it.

On the other hand, if I think that "all of it, regardless of how it is implemented, is a risk", I will probably have to stop using the libraries I mentioned above, and do a whole manual job...

  • What are the risks of using eval in a project?

  • I must always avoid it?

  • If the answer is yes to "should I avoid it," then should I also stop using libraries that implement it? After all, that can’t put my code at risk?

  • The eval should be used in some very specific cases (such as code generation only) or I can use it freely, as long as I am aware of what I am doing?

Note: Please do not edit and put tags as or , for the examples were only to show cases where eval was "well received". If there are examples of other languages that use it, you are welcome.

  • 1

    A "little eval" from time to time while does not hurt anyone, hehehe

  • 5

    I could give this answer here, although it is about Javascript. But I’m not sure what kind of answer you’re looking for. The eval exists, and there is no verdict uses/does not use, a Cad does as you want.

  • 1

    @Sergio want to leave this question here more to break down the prejudice (mainly mine, which I learned mechanically). But seeing these Ibraries, it really bothered me to remember these criticisms

  • 3

    @Guilhermenascimento to emphasize: "The misuse Eval can lead to code injection attacks"

2 answers

30


I’m going to start by saying that people use libraries without knowing if they have quality or not. Thus, how they use techniques, tools, methodologies, paradigms, technologies, courses, etc. without knowing if it is good for him in that context.

What are the risks of using eval in a project?

With the injection of malicious code or data it is possible to compromise the entire execution system. The eval() will execute the text you receive without any concern. Often the programmer imagines that something reliable will come, but usually the opposite happens.

I must always avoid it?

Yes, must avoid it "always". But if you have a real need you can use if you know what you are doing.

If the answer is yes to "should I avoid it," then should I also stop using libraries that implement it? After all, that can’t put my code at risk?

If the library is well made there is not a big problem. I wonder if the library used this because her programmers are lazy or there was a real reason for its use. If it is the first, that reason alone should be a warning not to use this library.

The decision should go through an analysis of the code and see if they sanitized the entire input of the function properly. If this was done the danger is small. It can always fail. It may be that they did almost right, but they left a loophole that some change in the code could pave the way for a vulnerability.

The Eval should be used in some very specific cases (such as code generation only) or I can use it freely, as long as I am aware of what I am doing?

If you’re going to use code generation the right way, I have doubts if the eval() really necessary. If it is something that is not exposed, it is already something positive. You can even use it freely if you’re aware of what you’re doing, but if you are, you won’t use it unless it’s fundamental. Sanitizing can be more complicated than one imagines. Of course there are always exceptions, but when there is one, it was usually simple to solve without the eval() since you don’t need to sanitize anything.

Usefulness of the Eval()

I don’t remember a problem I had to deal with eval() were necessary except when I used a very bad language that did not allow other forms. Just to get an idea was a language that did not have array, function, and reference. The day that this language happened to have these things, everything was solved without evaluating source code at runtime.

Doing right by him is so complicated that doing right without him is just as easy. Almost all uses of the function only becomes simpler if it leaves gaps.

Deep down the eval() in itself is not the problem, at least no more than SQL. Of course the eval() allows to cause greater damage (but may even be less in certain cases). The danger is not sanitize the text.

It is obvious that in scripts own, internal, very simple things, or even in cases where the text source is controlled 100% by the application, its use may be minimally appropriate, although probably not yet necessary.

In addition to the security problem there are performance and maintenance problems. Therefore, even in cases where security is not an issue, we should not abuse.

The danger of it is that it is addictive. One likes to have apparently simplified work, and begins to abuse.

Javascript

Interestingly the staff speaks very badly of eval() in Javascript and in fact it is better to avoid it, but think about it, what difference it makes to have a eval() in a code that the user has full control of? The JS problem is further down. Of course I’m talking about the use in browser. If you use Node, Deno or other technology for use on backend, the eval() should be avoided, or at least use with perfect sanitizing.

  • Bigown, the interesting thing about "libraries being reliable or not" is that in Laravel these libraries are installed "without our choice" because they are dependent on the project. That’s why, want to believe that they can be trusted... Also, right, where PHP got this idea of not being able to serialize a closure.. Anyway, this is it.

  • 3

    Speaks ill of eval in Javascript, but uses new Function... You’re kidding me, right

  • 1

    NPM was also reliable. https://www.kb.cert.org/vuls/id/319816

  • 3

    NPM was never trusted. People use, ams the fact that architecture has the permissions that are described in this article (in which a simple attack, and destroyer is described, but it’s only a bonus) is not safe. Only that people use it. Why is what "has" for Javascript and what front-end developers know how to use.

  • 1

    @jsbueno the intention of the comment is just this, people believe that things are reliable, without being. Note that the beginning of the answer goes in this direction.

  • 1

    Yes - the comment was agreeing - actually, I’m still a little altered after reading this article- I don’t really know the NPM - I knew it was bad, but I had no idea it was something so bad.

  • 2

    The idea of eval() would add a very basic support/ or metaprogramming features in the language?

  • 5

    @rray Would be. And the most powerful, easy to use and abuse. Hard to use right, hard to use when things don’t turn out as expected. It is a SUV without brake on the slope. Everything is very good, if nothing gets in your way.

  • 3

    I think the problem in general is not the resource eval, but of who is using. Until today I have never had to use the eval, but I kept seeing codes like eval('abc = 3'), where people go out using a resource unnecessarily just because they learned it.

  • @Maniero thank you so much for your reply, it is very good. I just got extremely curious about the JS problem, could you help me with that please?

  • 1

    @Jedaiasrodrigues JS has numerous problems, but that specifically is that it runs under user control, everything can be changed easily. And his other problem is that it attracts a lot of bad programmers who don’t understand what they’re doing. Interestingly most languages do not suffer so much with bad programmers, JS suffers, it gives a lot of room for damage with it, using eval() or not. There are sites that are being used for things even criminal for years and who did or who owns it does not know, because it is all done on the thighs.

Show 6 more comments

13

Consider that every technique, pattern or programming philosophy you learn is a weapon.

Algorithms with data structures are a pistol, you need to learn how to handle at least that if you want to go to the front. Hence object orientation, which is a rifle - you only become an efficient soldier when you can assemble and disassemble your objects with your eyes closed. Design patterns are sniper rifles, you destroy specific problems very accurately. Algorithm analysis (understanding complexity and O notation) is a missile launcher - no matter how big the problem gets, you’ll spend the same ammunition to end it.

The eval is like an intercontinental ballistic nuclear missile:

  • It has the potential to solve problems that would be very difficult to solve otherwise. In this case, adding external files, as Laravel does. However...
  • Public opinion will hate you. You will hear from many people that what you are doing is an atrocity;
  • There will be a lot of collateral damage: you are potentially opening your code to Javascript injection vulnerabilities. On the client side (browser) this is not so serious because in general all the code that runs in the browser is exposed to malicious people. But if you use JS on the server (Node.js, for example) and perform Eval on something that comes from the client side... May the God of programming have mercy on your soul;
  • The radiation takes centuries to dissipate - the maintenance of your code gets more and more complicated, since:
    ** Virtually no code analysis tool will want to touch the eval;
    ** Debugging becomes much more complicated;
    ** Flows become more difficult to map.

Finally, I will speak from experience. Most of the time when people use eval, they could have solved their problems by other means. In an attempt to alleviate the problems mentioned above, they end up doing more things that are not recommended and the maintenance costs turn into a snowball. If you think about using the eval, make sure that your problems cannot be solved in any other way before taking the idea forward.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.