26

Every time that someone mentions eval(), everyone says that there are "security issues" with it, but nobody ever goes into detail about what they are. Most modern browsers seem to be able to debug eval() just as well as normal code, and people's claims of a performance decrease are dubious/browser dependent.

So, what are the issues, if any, associated with eval()? I haven't been able to come up with anything that could be exploited with eval() in JavaScript. (I do see issues with eval()'ing code on the server, but client-side eval() seems to be safe.)

Peter Mortensen
  • 877
  • 5
  • 10
Stack Tracer
  • 514
  • 2
  • 5
  • 14
  • Client-side eval is only safe if you know the contents being passed come from the client performing the execution. – S.C. Jul 15 '15 at 16:50
  • Also only if you know they were not modified between the time the client generated them and the time the browser executes them. – S.C. Jul 15 '15 at 17:08
  • 3
    @S.C. Modified by whom, on what basis? In general, it is impossible harden a program against the end-user messing with its state with a debugger. But if it was modified by adding something that came from somewhere other than the client then obviously that would mean the contents don't come from the client anymore. – Random832 Jul 15 '15 at 18:54
  • 2
    @Random832, you are correct in that a developer should always assume the presentation layer can be modified by the client. They can break their own session and you shouldn't have to care about that. In practice, even if a client is not in an isolated, sterile environment, there is very little that could make a dangerous change without the previous existence of another compromise on the client's side (plugin, MITM, cache, physical access, etc). In theory, if you are not actively securing against it it is possible. How you want to balance practice and theory is up to you and your organization. – S.C. Jul 15 '15 at 19:15
  • 1
    What research have you done? Reasons to be wary of eval are described in a number of places. "nobody ever goes into detail about what they are" - Citation needed. This is clearly false. Just do a search on "eval" on this site and you'll find a bunch of posts that provide various levels of detail about risks with eval. See, e.g., http://security.stackexchange.com/q/25642/971, http://security.stackexchange.com/q/30365/971, http://security.stackexchange.com/a/90764/971, http://security.stackexchange.com/q/23192/971, to list a few I came across immediately. – D.W. Jul 15 '15 at 22:02
  • Related: [Exploiting JavaScript's eval() method](http://stackoverflow.com/a/18208029/413180) – SilverlightFox Jul 16 '15 at 07:27
  • cross-site duplicate: [Why is using the JavaScript eval function a bad idea?](http://stackoverflow.com/q/86513/1048572) (also [this search](http://stackoverflow.com/search?tab=votes&q=eval%20evil%20%5bjavascript%5d)) – Bergi Jul 16 '15 at 14:35

5 Answers5

32

eval() executes a string of characters as code. You use eval() precisely because the string contents are not known in advance, or even generated server-side; basically, you need eval() because the JavaScript itself will generate the string from data which is available only dynamically, in the client.

Thus, eval() makes sense in situations where the JavaScript code will generate code. This is not intrinsically evil, but it is hard to do securely. Programming languages are designed to allow a human being to write instructions that a computer understands; to that effect, any language is full of small quirks and special behaviours that are supposed to help the human programmer (e.g. the automatic adding of ';' at the end of some statements in JavaScript). This is all nice and dandy for "normal" programming; but when you generate code from another program, based on data which may be potentially hostile (e.g. string excerpt from other site users), then you have to, as the developer for the code generator, know about all these quirks, and prevent hostile data to exploit them in damaging ways.

In that sense, code generators (and thus eval()) incur the same conceptual issues as raw SQL and its consequence, SQL injection attacks. Assembling at runtime an SQL request from externally provided parameters can be done securely, but this requires minding an awful lot of details, so the usual advice is not to do that. This relates to the usual conundrum of security, i.e. that it is not testable: you can test whether some piece of code works properly on correct data, but not that it never works improperly on incorrect data. Similarly, using eval() securely is possible, but it is so hard in practice that it is discouraged.

All of this is said in all generality. In your specific context, eval() might be safe. However, it takes some effort to have a context safe for use of eval(), that actually needs eval().

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • Isn't `eval()` also prevalent in XSS attacks? – RoraΖ Jul 15 '15 at 16:05
  • 9
    Can you give a more specific example of how this would occur? I get that eval() executes a string, but I'd like to know what's uniquely problematic about it. A user can already run arbitrary JS through the console, and so I'm wondering what's different about the danger posed by eval(). – Stack Tracer Jul 15 '15 at 16:40
  • 5
    The difference is in where the eval contents comes from. If the string contents being passed to the eval call have the potential to be influenced in one way or another by a user or pulled from the database onto a page of more than just the one user who sourced those contents, you have a possibility for XSS. If you are just letting the user execute arbitrary JS within their own session, no harm done unless someone else can somehow influence the contents again. This is similar to dynamically generating javascript on the server side with unfiltered values sourced by user input. – S.C. Jul 15 '15 at 16:48
  • So, effectively, there is only a problem when several other parts of your system have been compromised? Of course, most of the usefulness of eval involves running scripts either written by the server, or scripts pulled from a database, in which case you just have to trust the DB. – Stack Tracer Jul 15 '15 at 16:58
  • 2
    Close but not necessarily. Suppose you run a site that lets me create content other users can see. Further suppose it lets me choose from a set of custom UI transitions to go along with that content and after investigation I find that set actually correlates to function names used in an eval statement. If I can find a way to append arbitrary JS to the transition code being executed, you will end up with a persistent XSS attack vector because I'm able to cause arbitrary JS to execute in the browser of anyone who view that content. That vulnerability would not exist if you didn't use eval. – S.C. Jul 15 '15 at 17:03
  • 2
    Bottom line is you are going to cause unknown code to execute in the users browsers. You can do your best to ensure it is safe code or code only from an accepted set of sources or behaviors, but at the end of the day you are still dealing with the principle of being as sure as you can be that nothing bad will execute as opposed to knowing for certain you do not provide the ability to execute anything harmful. If your scenario is simple enough that you can be sure it is always safe, it is almost always simple enough that you don't really need eval() at all. – S.C. Jul 15 '15 at 17:07
  • 1
    @S.C. What if we can assume that everyone with the ability to add those "UI Transitions" can be trusted? What if it were only available to administrators (or equivalent)? – Stack Tracer Jul 15 '15 at 17:18
  • Then you have progressed towards securing it by locking down its usage but still have several other avenues through which it could turn dangerous. Suppose another developer inherits your code and doesn't realize the requirements for keeping its usage secure -- how long do you think it will stay reasonably secure as he maintains the codebase? Suppose the I can find an injection in the selection/setting of the used transition instead of just in the adding of them (i.e. eval("someTransitionISelected();/*now do some evil stuff*/"))? Suppose you copy/paste for something similar but don't restrict? – S.C. Jul 15 '15 at 17:36
  • 2
    You then have to consider cost. What is the cost to implement and then maintain a secure usage of eval in that scenario as opposed to using some other design pattern for dynamic transition application? Most of the time keeping in the back of your mind that everything you do with that eval needs to pass a set of checks to remain secure is not worth using it in anything other than trivial scenarios. Good questions, though. – S.C. Jul 15 '15 at 17:39
  • 5
    Your question about "only available to administrators" is exactly where you need to change your thinking. Reflected XSS is used for this exact situation. I'm logged in as administrator to example.com. Someone sends me a link in an email like www.example.com?abc=some_malicious_javascript and like a fool I click it. If the abc parameter is vulnerable, then this attack will work. You must ensure your use of eval() is defended from this type of attack. – mcgyver5 Jul 15 '15 at 19:22
14

eval() is a possible vector for cross-site scripting.
Under normal circumstances, an attacker attempting XSS might want to get script <script></script> tags past whatever encoding, filters or firewalls might be in place. If eval() is there operating on user input, it eliminates the need for script tags.

Eval is present in many malicious scripts because it helps obfuscate code and / or sneak prohibited characters past filters. For this reason, eval() is often checked for in user input. So, when using eval() you are, potentially, providing the attacker one of their necessary tools. I'm robbing a bank and I know I don't have to sneak a gun past any metal detectors because there are a bunch in the umbrella stand inside the building.

mcgyver5
  • 6,807
  • 2
  • 24
  • 45
  • 2
    How is this different from just using the developer console? If I have a page with a big textbox, and a button which allows you to eval() everything in that textbox, I don't see what's different about that. – Stack Tracer Jul 15 '15 at 16:34
  • The difference is in where the eval contents comes from. If the string contents being passed to the eval call have the potential to be influenced in one way or another by a user or pulled from the database onto a page of more than just the one user who sourced those contents, you have a possibility for XSS. If you are just letting the user execute arbitrary JS within their own session, no harm done unless someone else can somehow influence the contents again. – S.C. Jul 15 '15 at 16:47
  • 8
    @Stack Tracer the goal of XSS is to execute the script in someone else's browser, not my own. – mcgyver5 Jul 15 '15 at 16:49
  • @mcgyver5, I'm wondering how that script could get to someone else's browser. – Stack Tracer Jul 15 '15 at 17:19
  • they click a malicious link or are forwarded by a malicious web site. – mcgyver5 Jul 15 '15 at 18:12
  • It would have to first be persisted (either through database or url state) or passed through a mechanism that the site provides for users to share non-persisted content with each other (chat, for instance). – S.C. Jul 15 '15 at 18:32
  • @mcgyver5, once a user has clicked a malicious link, I think that there are larger issues than eval(). Once we assume that they have already loaded a malicious website, there's no longer a need for XSS, as far as I can tell. – Stack Tracer Jul 15 '15 at 18:57
  • 2
    Not true. Pleae read about reflected XSS before making pronouncements about "no longer a need for XSS": https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29#Stored_and_Reflected_XSS_Attacks – mcgyver5 Jul 15 '15 at 19:06
  • @mcgyver5, how would a "reflected" XSS attack occur? That page is incredibly vague about how something like that could happen. – Stack Tracer Jul 15 '15 at 19:34
  • 1
    @StackTracer, a malicious link does not necessarily mean a link to a malicious website. In this context I believe mcgyver5 was referring to something like yourwebsite.com/?someParam=DoMaliciousThings where somewhere on your page you have a statement like eval(someParam) (highly simplified). That would be considered a reflected XSS attack since I could send you a link like that and when you open it your browser would execute my malicious javascript through the eval. Something like that looks more reasonable when you consider it could be combind with url encoding or shortened urls. – S.C. Jul 15 '15 at 20:02
  • "when a user is tricked into clicking on a malicious link, submitting a specially crafted form, or even just browsing to a malicious site, the injected code travels to the vulnerable web site" what is vague? – mcgyver5 Jul 15 '15 at 20:19
  • @mcgyver5, maybe the "HOW?" – Stack Tracer Jul 15 '15 at 22:46
  • 2
    @StackTracer Suppose Mallory and Alice both use a website that displays all error messages at /error.php?error=This+is+the+error+message. If Mallory sends Alice to /error.php?error= through, e.g. a link in an email, and the server has not properly sanitised user input, a reflected XSS attack will occur where Alice's cookies will be captured by the injected Javascript. – waiwai933 Jul 16 '15 at 00:10
5

As explained by others, one can use eval to dynamically create code which makes it harder to understand the control flow of the program. But, I don't consider eval much more evil than all the other ways to generate code at run time, like document.write(...), object.innerHTML(...) and others. While these are mostly used to change the DOM of the program they are also used to insert new code (i.e. add a script statement to the code, or a new element with some onXXXX handler etc).

And while eval is often used in attacks (XSS, malvertisement...) to circumvent filters or hide the real purpose of the code it is often used in an obfuscated form there, i.e. code like z='ev'; z+='al'; v=window; v[z]("alert(1)"). This means you are not on the safe side if you simply try to filter code with explicit calls of eval, because either the call is obfuscated or "good" functions like innerHTML are used for bad purposes.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
2

In addition to the great points made here, I would like to clarify: what you are essentially dealing with any time you use eval() is having to answer the following questions:

  • Is it worth securing?
  • How thoroughly can I secure it and is that level acceptable?
  • How confident can I be that it will stay secure over future evolutions of the codebase and development team?
  • How does the risk and amount of effort required by the above compare to the effort of constructing the code in such a way that execution of dynamically generated and possibly unknown code is not required?

If you have thought through these questions more completely than an attacker would and are still considering using eval(), go for it. You might find you grow tired of thinking that through over the course of your development career and start avoiding its usage simply on principle.

S.C.
  • 180
  • 1
  • 8
1

Some interesting answers and many of them amounts to is eval lets you execute any code therefore is a security risk. That is true but actually points to a much bigger problem your website is insecure. Anything that can be done with eval is better done with (Ctrl+Shift+I) anything I can do with eval is even easier with the debugging tool.

But there is one and only serious security is on involving multi-user websites like e-commerce sites such as your banks, insurance etc. The security issue arises when a 'bad guy' can execute Javascript in the security context of the 'innocent target guy'. In this scenario 'eval' is only a possible tool. Eval is a very powerful tool in Javascript and enables very powerful tools to be developed. The reason to avoid it is largely because it is so easy to abuse (bad or ill thought out programming).

NurulC
  • 11
  • 1