Friday, November 20, 2009

IE8 XSS Filter Bug

The register just ran an article (IE8 bug makes 'safe' sites unsafe) talking about a flaw in Internet Explorer 8's XSS filtering. I have researched the IE8 filter in the past and provided some of my thoughts on the matter.

As the article correctly states, I'm not aware of the actual flaw that has been discovered. According to the article, the flaw was made available to Microsoft several months ago and we can presume Microsoft is actively working on a solution.

With that said, I thought I would discuss some of the technical anomalies of IE8 XSS filter so that an organization can begin to evaluate if they should, at least temporarily, disable the IE8 XSS protection for the users of their site.

The intent of IE8's xss filter is to provide a feature which "makes reflected / “Type-1” Cross-Site Scripting (XSS) vulnerabilities much more difficult to exploit from within Internet Explorer 8." [blogs.msdn.com] I believe this is a noble goal which is similar to the noScript plugin for Firefox. The blog on msdn.com has a good example of the filter working as intended. The demo application has a reflected XSS vulnerability when accepting user data from the URL and returning it to the page without output encoding - classic XSS. IE8 xss filter detects this and safely renders the attack harmless.

How The Filter Works

Now let's take a look at how the protection works in the field. Luckily we have two sites available to illustrate the functionality. Google has turned off the XSS filter, with the header X-XSS-Protection: 0, whereas Yahoo has allowed IE8 to use the XSS filter as designed.

The following two links illustrate the changes that are made by the XSS filter when an attack is detected. Each link is the URL when searching for test<script>

http://www.google.com/search?hl=en&q=test%3Cscript%3E

http://search.yahoo.com/search?p=test%3Cscript%3E
[edit: 1/13/2010: It looks like Yahoo has also decided to disable IE8 XSS protection. Therefore the above link will not work to illustrate this example. Glad I captured the screenshot below. However, you can check out a similar example with Facebook]



The screenshot above shows the results when following the yahoo link. The reason that we see JavaScript on the rendered page is because the IE8 filter has performed a blanket replace of <script> with <sc#ipt> throughout the entire response. This does in fact render most XSS attacks inert, but it also has the unintended consequence of disabling all JavaScript on the resulting page.

Here is a snippet of the html from the Yahoo page. The change made by the filter is highlighted in bold. If you were to search through the entire response you would see that all <script> have been replaced with <sc#ipt>. Also, the final line with the "Search results" is an html entity encoding of the search value. This is performed by the yahoo page and unrelated to the IE8 filter. This is just yahoo practicing good design.

<html lang="en"><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=8"><sc#ipt>(function(){var h=document.documentElement;h.className+=" js";(new Image()).src='http://a.l.yimg.com/a/i/us/sch/gr4/srp_metro_20090910.png';})();</script><link rel="alternate" type="application/rss+xml" title="Yahoo! Search results for test&lt;script&gt;"

What's the Risk with the Filter?

There are two possible concerns that should be considered:
1. Is there a potential flaw in the output encoding that is being performed by the filter?
2. Does the act of disabling all script tags throughout the page actually introduce a new vulnerability?

#1
If an attacker could determine a flaw in the output encoding (which at this point is the translation of <script> to <sc#ipt>) then the attacker could potentially craft a value that would would evade detection by the filter. Alternatively, it may be possible to identify a weakness in the actual translation which allows an attacker to insert a particular value that will become malicious as a result of the translation.

A very basic example of this concept is a regex that would remove the first instance of the word "script" from a tag. If an attacker submitted <script> this imaginary filter would output <>. This would stop a basic attack. However, if an attacker submitted <scriptscript>then the resulting value would be <script> - which would be malicious. This is the idea of potential flaw #1.

#2
The second concern is that disabling JavaScript throughout the page will inadvertently introduce a new vulnerability. Consider a scenario where an application relies heavily on AJAX. What would happen if JavaScript was suddenly disabled as a result of the XSS filter? More than likely this would just break the page. This isn't a security concern, but a usability concern. I think I'm ok with the trade-off of usability and security for this example.

But what about a scenario where the application is using JavaScript as a security control to protect the user. (We all agree JavaScript cannot be used to protect the application from a user, but there are some possible scenarios where it could be used to protect the user from the content). For this scenario we will consider some sort of mashup application which uses JavaScript to perform output encoding on data from third party sources. For whatever reason the application made a design decision that the output encoding would be performed by client side JavaScript. In this scenario, IE8's disabling of script tags throughout the page could actually disable security related JavaScript code. Could this possibly allow malicious mash-up content from the third party source to now execute?

Should Your Site Disable The IE8 XSS Filter?

I wouldn't rush to judgment and disable the filter. At this point we have word that there is a potential weakness and it is being addressed by Microsoft. We don't know of a public exploit at this time and hence can't thoroughly evaluate the impact to our respective applications. I think it would be prudent to review the impact of the XSS filter on your particular application and determine the effects of suddenly disabling the script tags within the page. More than likely this will result in the page not functioning correctly. But hey, that's not so bad if it protects the user from XSS compromise.

-Michael Coates

5 comments:

  1. Looks like scenario #2 is pretty much right on the mark. Here is some more info from someone with specific knowledge of the flaw:

    http://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/

    ReplyDelete
  2. Has anyone had any luck actually disabling the IE 8 "feature" using the header? this breaks an ajax app of mine and I've tried the X-XSS-Protection : 0 header, verified the header is in place, and it still prevents the content from being shown.

    In my case its blocking an xml request submitted through an iframe which contains legitimate page content. How frustrating.

    ReplyDelete
  3. Dan,

    A few key things to remember. The X-XSS-Protection header has to be added to the HTTP Response. Is that where you are adding it? In your case, you would need to have control of the site your are referencing within your iframe. Adding it to the Request has no impact.

    During testing, I've added the header to all of my responses using a web proxy. This worked just fine and IE8 honored the flag.

    -Michael

    ReplyDelete
  4. Unfortunately, yes. I have tried adding the http response header from both IIS and through the web scripting language I use. then I used a network sniffer to follow the http stream and verified the server was responding with the X-XSS-Protection: 0 header, and it was.

    Did you actually test a broken case with and without the flag, to be sure it was honoring the flag? Maybe with a recent patch MS disabled the disable feature.

    ReplyDelete
  5. Yep, I just tested it again and the flag is definitely being honored. I used fiddler to add automatically add the x-xss-protection: 0 flag to all my responses for the test.

    I also tested within an iframe using a known xss example from xssed.com. The x-xss flag was still properly handled.

    Not sure what is happening with your example. Try working with another page and fiddler proxy to get the setup working right. Then give it a try with your example.

    Now, I've not tried with AJAX. So, let me know what you find.

    ReplyDelete

Note: Only a member of this blog may post a comment.