Is Eval good or bad guy?

32

They speak very poorly of eval , but sometimes I wonder if it really is the problem or it is the person who is sitting in front of the computer (I support the programmer).

My entire life (in programming) I've heard criticisms, jokes, zoeiras on top of this eval function, but the curious thing is that even those who mock, end up using libraries that use it internally, without knowing it. p>

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

Example (I removed 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's already discontinued, but it's not in a distant era like this (its version is for PHP 5.3). But it would not be surprising if one of the critics of eval had used this framework without knowing that information.

And yet I give another example, which many programmers also use, but without knowing it. The SuperClosure that is used in Laravel 4 and Laravel 5. This library has the purpose of providing a possibility to serialize closures in PHP, since natively closures in PHP do not support serialization. This library becomes useful for those who need to use queuing systems, such as Beanstalkd, where past information is usually a string , and therefore the data in PHP 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 library classes presented above, remembering that they are just two examples, but there must be other cases, I was wondering if I should still keep talking bad about eval or just do an analysis and evaluate when it's good or bad to use it.

On the other hand, if I think that "every eval, regardless of how it's implemented, is a risk", I'll probably have to stop using the libraries I mentioned above, and do an all-manual job ... < p>

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

  • Should I 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, can not this put my code at risk?

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

    
asked by Wallace Maxters 16.05.2016 в 22:38
source

2 answers

27

First, let me 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. not knowing if it's good for him.

  

What are the risks of using eval in a project?

By injecting code or malicious data, you can compromise the entire execution system. eval() will execute the text you receive without any concern. Often the programmer imagines that something trustworthy will come, but it tends to be the opposite .

  

Should I always avoid it?

Yes, you should always avoid it. But if you have a real need, you can use it if you know what you're doing.

  

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

If the library is well made there is not a big problem. I wonder if the library used it because its programmers are lazy or there was a real reason for its use. If this is the first one, this 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 every entry of the function properly. If this was done the danger is small. It can always fail. It may be that they have done almost right, but they have left a loophole that some change in the code may pave the way for a vulnerability.

  

Should eval be used in some very specific cases (for example only in code generation) or can I 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'm not sure if eval() is really necessary. If it's something that is not exposed, it's something positive. You can even use it freely if you are aware of what you are doing, but if you do, you will not use it unless it is critical. Sanitize can be more complicated than the person imagines. Of course there are always exceptions. But when there is one, it was usually simple to solve without eval() since you do not need to sanitize anything.

Eval utility ()

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

Doing right is so complicated that doing the right thing without it is so easy. Almost every use of the function just gets simpler if you leave holes.

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

It is obvious that in scripts , internal, very simple things, or even in cases where the text source is 100% controlled by the application, its use may be minimally adequate. >

In addition to the security problem there are performance and maintainability issues. Therefore, even in cases where security is not a problem, you should not abuse it.

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

JavaScript

Curiously, people talk very poorly about eval() in JavaScript. In fact it's best to avoid it, but think about it, what difference does a eval() have in a code that the user has full control over? The problem with JS is lower.

    
answered by 16.05.2016 / 22:52
source
12

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

Algorithms with data structures are a pistol, you need to learn to handle at least this if you want to go forward in battle. Hence comes object orientation, which is a rifle - you only become an effective soldier when you can assemble and dismantle your objects with your eyes closed. Design patterns are sniper rifles, you destroy specific problems very accurately. Analyzing Algorithms (Understanding Complexity and O Notation) is a missile launcher - no matter how much the problem grows, you'll spend the same ammunition to do away with it.

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, include external files, as Laravel does. However ...
  • Public opinion will hate you. You will hear from a lot of people that what you are doing is an atrocity;
  • There will be a lot of collateral damage: you are potentially opening your code for Javascript injection vulnerabilities. On the client side (browser) this is not so serious because in general all 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 ... Let the programming God have pity on your soul;
  • Radiation takes ages to dissipate - maintaining your code is getting more and more complicated, since:
    ** Virtually no code analysis tool will want to touch on eval ;
    ** Debugging becomes much more complicated; ** The flows become harder to map.

To conclude, I will speak from experience. Most of the time people use eval , they could have solved their problems by other means. In an attempt to mitigate the problems mentioned above, they end up doing more things that are not recommended and the maintenance costs have seen a snowball. If you think about using eval , make sure your problems can not be solved in any other way before you get the idea straight.

    
answered by 16.05.2016 в 23:04