The Evils of Eval

[article]
Summary:

If you're a developer who uses JavaScript, or if you know one who does, Bryan Sullivan has some advice for you: take a few moments to acquaint yourself with the dangers of eval and its related functions, then learn to better secure your applications from attackers. In this article, he compares the command to other major security issues like buffer overflows, SQL injection, and cross-site scripting.

If you've ever wanted to learn how to hack software applications, there's basically only one rule you need to follow: get the application to treat your input as code. It sounds simple, but almost every major vulnerability works on exactly this principle. Buffer overflows are exploited by getting the target application to treat input as assembly code and run it. SQL injection vulnerabilities are exploited by getting the application to treat input as SQL code. Cross-site scripting (which should have been named "JavaScript Injection," in my opinion) is just input treated as script and executed on the victim's browser. With all the effort our industry goes through to keep these vulnerabilities out of code, it makes no sense to design applications explicitly to accept untrusted input and execute it as code. Yet, that is exactly what developers do when they write applications that use the JavaScript eval command.

In a nutshell, the eval command takes whatever string you pass it as an argument, then compiles that string, and executes it. There are all kinds of problems with this design pattern: it has poor performance,  uses too much memory, and is difficult to maintain. Let's focus on the security aspects. If an attacker is able to inject arbitrary script code into an input and get eval to execute that code, that is essentially the equivalent of the impact of a successful cross-site scripting attack. In my previous column, “
Show Some Respect to Cross-Site Scripting,” I wrote about how cross-site scripting attacks can have extremely serious consequences, ranging from enabling phishing attacks to session hijacking and even self-propagating Web worms. Again, all of these attacks are still possible when executed through an eval injection.

Hopefully I"ve convinced you that using eval is a bad idea, and you're about to go scour your code looking for instances of it. That's a good start, but eval has cousins that go under different names but still can wreak the same trouble in your code. Two of these are setTimeout and setInterval. The setTimeout function simply adds a delay argument to eval. Instead of being immediately executed, the code argument passed to it is executed after the specified delay time. Similarly, the setInterval function adds an interval argument, and the code is executed every time the amount of time specified by the interval elapses. These calls are functionally equivalent to eval, and you should avoid or remove them whenever possible.

Speaking of "functional" equivalents to eval, there's another you should be aware of: the function constructor. It is possible to define a function by declaring a new function object instead of using the more common function definition syntax (function square(x) { return x * x; }) or function literal syntax (var square = function(x) { return x * x; }). When declaring function objects in this manner, you pass the function body (i.e., the code to be executed) as a parameter to the Function constructor, like this:

var square = new Function('x', 'return x * x;');

If an attacker were able to inject code into the function body parameter.  For instance, if the parameter was built using user input instead of being hardcoded as in the examples above, then he could potentially exploit the weakness.

You might think that your use of eval (or its brethren) is safe, as you're not passing untrusted input to it. The problem is that it can be difficult to tell exactly what input is trusted. Query string parameters and form field values are obviously untrusted user input, but so are headers and cookies. One popular use for eval is to use it to parse JSON strings into JavaScript objects. Can you be certain that the JSON you're parsing is safe, even if you're pulling it from your own server? If the answer to this question is no, you shouldn't be using eval.

As a final thought, I'd like to note that the
Microsoft SDL includes a recommendation against using eval and its equivalents.  It suggests using Casaba Security's Watcher tool that I mentioned in More Free Security Tools to help find these in your code. Happy vulnerability hunting!

Tags: 

About the author

CMCrossroads is a TechWell community.

Through conferences, training, consulting, and online resources, TechWell helps you develop and deliver great software every day.