2

From OWASP AJAX Security Cheat Sheet:

Eval is evil, never use it. Needing to use eval usually indicates a problem in your design.

I understand that evaling untrusted JS code can lead to a whole world of pain, nonetheless I fail to understand the categoricity of OWASP's prohibition.

The way I understand things it is perfectly possible to use eval securely, namely when the eval'd code is trusted.

I'm developing a hobby web app (game) in my spare time (unpublished yet). In this app I do use eval. Even though this is a single page I sometimes feel it is simpler to make the server send chunks of HTML code to the browser instead of having the browser construct the page from scratch. So this is what I'm doing:

  1. Have the browser start an XMLHttpRequest to the server for a page fragment;
  2. Load the received HTML code (this implies innerHTML, which incidentally is another thing OWASP warns agains)
  3. Since innerHTML doesn't run JS code present in the assigned fragment, search the loaded HTML code for script tags and eval them.

By doing this I clearly violate OWASP's guidelines. Nonetheless I fail to see how this is any less secure than normal loading a HTML/CSS/JS page from the server w/o AJAX, just by typing the page's address in the browser address bar. In both cases (loading the page from address bar vs innerHTML'ing and - gasp! - evaling the response from an AJAX call to the server) there is an implicit assumption of trust to this webpage. If the server is compromised and starts emitting rogue HTML / JS code then everyone is equally screwed even if no evil eval is used. Otherwise, everyone is equally safe.

However I know that me not being an expert I likely have very limited understanding and if OWASP categorically forbids something then they likely have good reasons for this. Let me ask then, what are the risks of doing what I described?

  • NAA, but: you've picked a counter example that people don't usually have in mind when they talk about using eval, so to some extent you are arguing a bit of a strawman. Indeed, in this case you wouldn't even have to use eval anyway. You could just take the script tag and write it to the page. You aren't executing dynamically generated code (which is what OWASP is talking about), you are simply dynamically loading pre-written code, which is what everyone already does. You're just doing it in a somewhat unusual way. – Conor Mancone Dec 3 '18 at 19:56
  • @ConorMancone (a) I have to use eval AFAIK, because I can't take the script tag and write it to the page, or more precisely I can but it won't execute due to the semantics of innerHTML? (b) I don't think I'm using a strawman argument here because of the categoricity of OWASP's recommendation: to my mind the world never accepts no counter-examples. Things would be different if they said be careful about or even avoid or something like that, but they did say never! – gaazkam Dec 3 '18 at 20:01
  • if you need to run new code, you need to run new code: eval() does the same as a dynamic script tag workaround would. the "rule" is free of nuance: KISS. There's several decent reasons to use eval(), but also 1,000,001 bad one... If you use jQuery's .html(x) instead of .innerHTML=x, eval is called – dandavis Dec 3 '18 at 20:17
  • @dandavis And since eval is called in your jQuery example, aren't we digressing from the point that eval is supposed to introduce inherent security flaws? Wrt KISS: I may be failing to get something, but: what is dynamic script tag workaround? Search the response, copy the contents of all script tags, construct new script tags, insert them? Seems less simple than just evaling all script tags. I'm willing to accept that eval is evil, but I'd just want to know why – gaazkam Dec 3 '18 at 20:25
  • @gaazkam You don't have to use innerHTML, nor even jQuery. You can just write the script tag to the page directly: stackoverflow.com/a/13122011/1921979 However, I actually still agree with the OWASP suggestion, and suspect you are suffering from some design problems. For instance what you are doing stops you from using some CSP features that would block many XSS attacks from happening in case you had a failure elsewhere in your security chain. – Conor Mancone Dec 3 '18 at 21:15
2

tl/dr: For a game you are working on for fun with no one else's information at risk then sure - do whatever makes your life easiest. You're welcome to balance security and usability however you want as long as you aren't risking other people's information. What you are doing certainly isn't uncommon. However, this decision does in fact prevent you from following some best security practices, and so overall I think that advice from OWASP is perfectly applicable.

It's true that what you are doing isn't especially crazy, isn't necessarily uncommon, and isn't substantially different than a more typical use-case . It's also true that statements like "X is evil don't ever do it" are a bit over the top, and rarely entirely true. However, I think there are a number of points you are still missing (even after McMatty's mentioned an important detail in his answer), so I figure it's worth discussing more. However there is one important caveat worth mentioning first:

Security is never "All or nothing"

Security is always a balancing act. The fundamental question of security is basically "is this secure enough for my purposes?" An anonymous-cat-picture-voting site hardly needs any security at all, unlike the nuclear-missile-launching site. If you understand the implications of the decisions you make and are happy with the balance your application strikes between "this is easy for me to write/maintain" and "this is secure enough for my purposes" then it doesn't really matter what OWASP says (assuming, of course, that you are actually making an informed decision and aren't just saying "I don't care if my customer's credit cards get stolen"). If you're just making a game for fun then it doesn't really matter. Of course if it later has success and you start integrating a payment portal for in-app purchases, then you might find yourself having to go back and revamp your entire system for better security.

All that being said, what does OWASP's advice mean for your use case? Here are some details I think you may be missing

  1. You don't actually have to use eval here. If you have a script tag then rather than evaling its contents you can just create a script tag and write it to the body (see this question). Of course, there is little practical difference between using eval and writing a script tag to the body so this is somewhat pointless...

  2. With javacript defined directly on the page you can't use a strict CSP to stop XSS attacks. With a sufficiently strict CSP you can tell the browser not to allow any inline javascript to execute on the page. This is very effective at stopping an XSS attack if someone manages to find one in your system. However, you can't do it if you have your own inline javascript.

  3. External javascript files can have a hash attached that will prevent the browser from using the file if does not match (aka if the external file has been tampered with). This doesn't matter as much in your case because you are loading your own internal resources, and if your internal resources are tampered with then you have a much bigger problem that a hash won't stop. However, defense-in-depth suggests that such steps can be valuable anyway. For instance, a larger app may have scripts delivered from different "services" in your system, and an attacker may gain access to only one area of your system. By including sub-resource integrity checks even on internal systems, you can easily provide a barrier that might stop an attacker from compromising further parts of your system. This is impossible with inline scripts.

  4. Needing to use eval usually indicates a problem in your design. I'm highlighting this statement from OWASP, because I think it is applicable and you are overlooking it. You said you are doing this because sometimes you find it easier to have the server send down chunks of HTML instead of having javascript build the page. Apparently when this happens sometimes the server even sends down more javascript itself. All this to say: yes, I think there is a problem with your design. Don't get me wrong, that doesn't mean you need to go and overhaul everything. However you have some pages where javascript builds the page, some places where the server builds the pages, and some pages where the server builds the page and also sends down more javascript to control the new page. This might very well be easier for you right now, but from an outside perspective I think it's easy to say that you really do have some design "smell". That doesn't have to be a big deal, and I don't mean that to be negative, because we all have to make design decisions that make the most sense to us. Still, whether you realize it or not, I think you are in many ways proving the truth of what they are saying.

| improve this answer | |
1

The risk is you have enabled code execution from the eval tag if an attacker can get content into it. You trust the content so that not be an issue but as mention it is a design flaw and laziness. Laziness leads to bugs and security issues.

Content Security Policy is very specific to stop what you are attempting here and their are multiple good ways to achieve what you are doing instead. Just because you find a way to get something to work and its easy doesn't make it right.

| improve this answer | |
  • 2
    OK so you repeat that eval is bad, I get it, everyone keeps saying it is bad, but this doesn't answer the question why? – gaazkam Dec 3 '18 at 20:22
  • The very first line of my reply - JavaScript code execution within your page. – McMatty Dec 3 '18 at 20:28
  • Because if an attacker can get you to execute his code (which is much easier with eval) then he can attack your software and then potentially your users. Btw, a simple Google search will turn up many pages on this. Here's one: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, scroll down to "Do not ever use eval!" – Swashbuckler Dec 3 '18 at 20:29
  • @Swashbuckler Yes I did read it and? Again, what I wrote in my Q remains unanswered: While it is clear that JS code execution within my page from an arbitrary source is terribad, is eval still bad if I only execute code AJAXed from the server of my webapp? How is it any easier for an attacker to execute his code that way than if I abandon eval and only run JS code returned from this same server when the user types the address of my app in the browser address bar? In both cases code from this server is equally trusted and executed in the same context? – gaazkam Dec 3 '18 at 20:35
  • @McMatty "The very first line of my reply - JavaScript code execution within your page." OK but in your reply you said: "You trust the content so that not be an issue" but then you continue: "as mention it is a design flaw and laziness. Laziness leads to bugs and security issues." OK so from what you said the reason eval is a design flaw is not applicable here so why is it nevertheless still a design flaw? – gaazkam Dec 3 '18 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.