Select Monthly Archives
- March 2018
- February 2018
- December 2017
- November 2017
- September 2017
- August 2017
- June 2017
- May 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- March 2016
- October 2015
- September 2015
- July 2015
- May 2015
- March 2015
- February 2015
- January 2015
- December 2014
- September 2014
- August 2014
- July 2014
- June 2014
- March 2014
- January 2014
- December 2013
- September 2012
Written By: Ryan Borden January 23, 2017
You implemented a blacklist. That’s good enough, right?
So you’ve been testing the web application you built for Cross Site Scripting vulnerabilities, and you’re pretty sure that your defenses are solid. You’ve checked all of the inputs to make sure that an attacker couldn’t break out of the source code in a way that leads to XSS. You even dusted off your cheat sheet to help you build out a really comprehensive blacklist. Your site is bullet-proof, right? Well, probably not.
The problem with relying on a blacklist is that you don’t know, and can’t know every possible injection which exists and which will exist in the future. While blacklists are easy to implement and even come bundled with a WAF or framework, they also tend to be easy for attackers to by-pass. Technologies are always changing, and with those changes come introductions to the HTML standards and to browser parsers which attackers can exploit. As a hacker, one of my favorite things to do is to find a way to by-pass your blacklist. Your blacklist is a challenge to my skills, and I will defeat it. Over the years I have encountered several really good blacklists, and I have defeated the overwhelming majority of them. With those victories has come a list of unusual injections which I have added to my own cheat sheet, and now I am going to share some of my favorites with you.
Really Internet Explorer? Really?!
Let’s start off by picking on everyone’s favorite browser to download other browsers, Internet Explorer. This notoriously insecure browser has been a favorite target for attackers over the last few decades. Poor IE just wants to be user friendly to both programmers and users, but in doing so it has historically opened the floodgates for hackers. We’ll start off by looking at injections which exploit IE’s loose rendering rules.
Injection: <%foo onmouseover=“confirm(1)”>
Beyond that, this injection will execute in any IE 9+ browser as long as the Document Mode is set to 9. I was recently testing an application which was nice enough to set this Document Mode by default, and this is not an uncommon configuration. If an older application was built back in the IE 9 days, programmers are going to be incline to keep the Document Mode in-line with the old standards so that they don’t have to rebuild the whole application.
Injection: <img src="x` `<script>alert(1)</script>"` `>
This injection takes advantage of Internet Explorer 8’s parser by creating an unbalanced attribute delimiter. IE 8 treats any tag as plaintext in cases where the attribute delimiters are unbalanced; in this example caused by the ` `. By injecting backticks into the src attribute the attacker can put their injection in plaintext, and once the attacker has placed themselves into plaintext space it is game over.
IE only onEvents
I’m not going to spend too much time on this because we all know how onEvents work. Microsoft introduced a short list of onEvents which are exclusive to their IE 10 & 11 browsers. This is great for hackers because these onEvent tend to be lesser known, so a lot of blacklists fail to include them.
IE 10 & 11 onevents
IE 11 onevents
Move over IE, here comes Firefox.
Apparently the developers at Mozilla were absent on the day when their teacher went over George Santayana’s famous quote:
“Those who cannot remember the past are condemned to repeat it”.
They are beginning to repeat some of IE’s mistakes. In an attempt to be more developer/user friendly, Firefox has introduced some new elements and attributes which are exploitable and unique to their browser.
Injection: <input type="hidden" vulnerable-parameter=”XSS” accesskey="x" onclick="alert(1)”>
This is one of my new favorites because it helps a hacker get a relevant injection into those troublesome hidden inputs. I’m sure we all know the tired style expression injection which only executes in IE 7, and has been used to death for hidden inputs because it was the only thing that worked. Well Firefox has changed the rules of the game and given us a fresh new way to inject malicious payloads into hidden input fields with the accesskey attribute. The accesskey attribute allows for onEvents in a hidden input to be triggered when a user presses a specific key combination. In Windows environments the key combination is alt + shift + the specified access key (in this case “x”). In OS X environments the key combination is ctrl + alt + the specified access key. Yes, this will require a little more social engineering in order to get a victim to select the specified key combination, but someone will fall for it and an attacker will get their victim.
Hack on all the browsers!
These next few injections are not limited to a specific browser, and help to further highlight why a blacklist is insufficient.
Injection: <marquee behavior=“alternate” onbounce=“confirm(1)”>XSS</marquee>
Break out your flannel shirts and that copy of “Jagged Little Pill” because we’re going back to the 90’s for this one! That’s right, this injection is using a Marquee tag. Yes, it does still work in the modern world, and its associated onEvents still work with it. The great thing about this injection is that it’s so old almost everyone has forgotten about it.
The oft overlooked data scheme URI has allowed me to get past several blacklists. This injection allows for URI space to become whitespace, and then allows for the injection to be further obfuscated by encoding HTML code using Base64. Whether an attacker is landing in a space where they can define a URI (such as a redirect parameter), or they have created the URI space with a tag, this injection will prove useful for exploiting an application.
All hope is lost! (Just kidding)
So now that you have seen that your blacklist is probably not going to be sufficient what are you supposed to do? No, you cannot just copy my injections into your blacklist and call it a day. Wait! Don’t rm –rf your whole server! There is another answer; a solution which will protect your application and its users from all the bad guys who want to ruin all of your hard work. The best solution is to output encode all user supplied input appropriately based on the context in which the input is being used, and where possible to validate the input against a whitelist of acceptable characters. I know, that solution sounds too simple but that’s really all it takes to prevent 90% of the XSS attacks your application will see (that other 10% is made up of DOM XSS which is a whole different topic). If you ensure that all of the input which comes from the client is properly validated and output encoded then the chances are, XSS payloads will never execute in your application. As a final note I would like to emphasize that ALL inputs need to be validated and checked, not just the ones where you are expecting user supplied data. Parameters which are supplied input via drop-down menus in the UI, hidden input fields, user-agent strings, cookies, and more are all viable attack surfaces to a hacker.