Limiting Script Injection in Dynamic Script
One of the places you see script injection is actually inside of dynamically-generated javascript. XSS doesn't just have to happen in HTML, and it's actually somewhat surprising how often it happens in Javascript.
If the dynamically-created script is in an HTML page, a handy trick to work around this is to actually move the dynamic parts outside of javascript. When you include dynamic pieces with user-controlled data inside the script, there are so many more characters to deal with, and the attacker doesn't have to generate HTML tags to get their script executed.
Take the following example:
...
<script>
var name = '<%= request['name'] %>';
</script>
...
In that simple example, normal HTML encoding won't work because you've got apostrophes. But if you're inside double quotes, you have to deal with those, and apostrophes might be perfectly legitimate characters. To deal with that easily, just replace it with something like this:
...
<script>
var name = document.forms['holder'].elements['uname'].value;
</script>
...
<form name="holder">
<input type="hidden" name="uname" value="<%= encode(request['name']) %>"/>
</form>
This way, you don't have to think about what kind of quotes you're in (if any), you just let your framework's trusty encoding library do the heavy lifting for you.
wouldn't be the following much more easier:
ReplyDelete...
<script>
var name = decode('<%= encode(request['name']) %>');
</script>
...
with regards
Its an interesting idea, but I don't think that it really solves anything other than quirks like being able to inject </script> into a variable and stop execution, and then have some malicious html below that.
ReplyDeleteI say this because while Javascript parsers are complex, they are no more complex than HTML rendering engines, and while inserting data into HTML is better understood, it is no less difficult.
In your example you mention that its easier to escape things in HTML because they have double quotes, but there's nothing stopping a person using double quotes to encapsulate Javascript variables, or using single quotes or grave accents, or nothing whatsoever to encapsulate HTML attributes.
But yes, it does reduce the problem to something they have already solved, so I guess that's something. Just as long as developers don't start evaling the content, ;) But shouldn't frameworks have functions to escape things in different situations anyway?
P.S. How do you get the "Email this • Save to del.icio.us • Digg This! • Slashdot Bookmark This" Links?
Tibor:
ReplyDeleteIn your example, you're javascript decoding something that your framework has HTML encoded. In order to properly encode there, you need to javascript encode, meaning that you need to backslash the types of quotes you're in, meaning the encode function from your tool needs to be able to see the javascript context. And if the variable is inserted outside of quotes, then it will cause a javascript error (at best) if the attacker includes any quotes - which they won't necessarily need.
kuza55:
If you're using an HTML encode function provided by your framework, the HTML is much more elegant, assuming you use double quotes in your HTML tags for attribute values. The problem with javascript encoding a string is that you have to know if you're inside a string literal or not, and if you are, what kind of delimiters are being used. With HTML encoding, the encoding is the same, regardless of whether you're inside an attribute or inside a text node.
For the Email, del.icio.us, digg, and /. links, I use a FeedFlare from feedburner.
I've been meaning to post this for a long while now, but I was oh so very wrong.
ReplyDeleteWith the way browsers are written, it is much safer to fall back on something we are getting towards figuring out and, step by step, solving.
Case in point: http://sla.ckers.org/forum/read.php?2,7947
Since seeing that post I've really warmed up to this idea of reducing the problem to one we're constantly working on.