Context Matters for Cross-Site Scripting Filters

During a recent pen-testing exercise, Cross-Site Scripting (XSS) was as usual the most common issue found. Some sites had issues numbering in the hundreds (with nearly every parameter on every page being vulnerable). This should no longer be surprising to anyone; XSS has been one of the most common vulnerabilities for years. What was most interesting was that in several of these cases, the web site in question was doing very effective HTML filtering. They were either completely stripping all HTML tags, doing some crazy parse-and sanitize routine, or some other filtering that would make a traditional XSS attack impossible. However, these pages were still vulnerable. Why? They were reflecting parameters inside of JavaScript, where different rules apply.

 

When a parameter is reflected inside of JavaScript, an attacker no longer needs to inject an HTML tag to execute script. After all, a script is already being executed. It’s usually only a matter of using one or two characters to break out of the current statement to begin executing arbitrary code. Consider the following simple case:

 

http://example.com/news.php?date=2010-01-01

...

news.php:

<script>
make_ up_some_news('<?php echo strip_tags($_GET["date"]); ?>');
</script>

 

PHP's strip_tags() would remove a traditional XSS attack of the form “<script>alert('XSS');</script>”, but no tags are needed here. http://example.com/news.php?date=');alert('XSS');// will execute script without needing < or >. Even PHP’s htmlspecialchars() would not fix this, unless it was also passed ENT_QUOTES, as it will allow single quotes to pass through by default. HTML only defines the following characters as “special”, which could break the flow of the page:

 

Character

Description

"

quotation mark

'

apostrophe 

&

ampersand

less-than

greater-than

 

To protect a reflection in JavaScript, you would need to filter out newlines, semicolons, curly braces, square braces, parenthesis, and nearly every other non-alphanumeric symbol, depending on where the parameter is being reflected. Reflecting a parameter inside of a <style> tag or attribute has similar problems. It’s not necessary to use angle brackets inside of CSS in order to execute JavaScript, fetch a remote URL, or do other potentially dangerous things.

 

Of course, any list of “dangerous” characters or sequences runs the risk of being non-comprehensive. By far the safest and easiest way to protect yourself is to use a whitelist-style filter instead of a blacklist-style one. Whitelisting involves accepting only what is ‘good’ instead of trying to reject everything that is bad.  Instead of using strip_tags, in this case, try to parse the input as a valid date matching the yyyy-mm-dd pattern you expect. If you’re expecting an integer, require an integer, etc. If it doesn’t match, throw an error. This is not a time to be liberal with what you accept (and reflect)! If these pages were only accepting input in a specific format instead of trying to remove “dangerous” characters or sequences, there would not be a problem, regardless of where it was being reflected.

Comments
China VPN(anon) | ‎01-30-2012 10:08 AM


Great post, I think people should acquire a lot from this website its really user friendly .

Leave a Comment

We encourage you to share your comments on this post. Comments are moderated and will be reviewed
and posted as promptly as possible during regular business hours

To ensure your comment is published, be sure to follow the Community Guidelines.

Be sure to enter a unique name. You can't reuse a name that's already in use.
Be sure to enter a unique email address. You can't reuse an email address that's already in use.
Type the characters you see in the picture above.Type the words you hear.
Search
Showing results for 
Search instead for 
Do you mean 
About the Author


Follow Us
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation