Thursday, July 4, 2013

XSS Defense in Depth (with Rack/Rails demo)

Quick introduction to the XSS problem
XSS is not only about scripts. Overall it happens when attacker can break the expected DOM structure with new attributes/nodes. For example <a data-remote=true data-method=delete href=/delete_account>CLICK</a> is a script-less XSS (in Rails jquery_ujs will turn the click into DELETE request).
It can happen either on page load (normal XSS) or in run time (DOM XSS). When payload was successfully injected there is no safe place from it on the whole origin. Any CSRF token is readable, any page content is accessible on site.com/*.

XSS is often found on static pages, in *.swf files, *.pdf Adobe bugs and so on. It happens, and there is no guaranty you won't have it ever.

You can reduce the damage
Assuming there is GET+POST /update_password endpoint, wouldn't it look like a good idea to deny all requests to POST /update_password from pages different from GET /update_password?

Awesome! But no, Pagebox is a technique for the next generation of websites because of many browser problems.

Thankfully similar technique can be implemented with subdomains:
www.site.com (all common functions, static pages)
login.site.com (it must be a different subdomain, because XSS can steal passwords)
settings.site.com
creditcards.site.com
etc

App serves specific (secure) routes only from dedicated domain zones, which have different CSRF tokens. All subdomains share same session and run same application, upgrade is really seamless, user will not notice anything, redirects are automatic.

How to add it to a Rack/Rails app

You only need to modify config.ru (I monkeypatched rails method, it's easy to do same for a sinatra app)

It fails if you GET/POST www.site.com/secure_page from www page because middleware redirects to secure.site.com (which has different origin - you cannot read the response)
It fails if you POST to secure.site.com/secure_page with www page CSRF token because secure subdomain uses different CSRF token which www doesn't know.
Neat!

The demo is a basic prototype and may content bugs, here you can download the code.

There is also a subdomainbox gem. I hope to see more Domain Box gems for ruby apps along with libraries for PHP/Python apps. Maybe we should add this in Rails core, telling other programmers who cares about security the most?

[PUNCHLINE] Is it you? We're looking forward to hearing from you. Sakurity provides penetration tests, source code audit and vulnerability assessment.

9 comments:

  1. XSS is about scripts, though, because it's called cross-site _scripting_) It is an attack leading to the execution of a client-side script in context of the website's origin. In other words, this attack is about SOP bypass, and nothing else.

    There is no any SOP bypass at your example with CLICK. So, is just a content spoofing, not XSS.

    ReplyDelete
    Replies
    1. I can't fully agree with you.
      Yes if we read it here https://www.owasp.org/index.php/Content_Spoofing it says XSS and spoofing are nearly same thing.
      My example cannot be called content spoofing because it uses victim's code via data- attributes. This is scripting based on predefined user scripts - IMO

      Delete
  2. OK, so your example describes thing like 'same-site-scripting' but not 'cross-site'. This is important in terms of XSS classification.

    ReplyDelete
    Replies
    1. same-site means it doesn't send information to 3rd parties? but many XSS do so, they can only update status or change profile details for example. I don't think there's different between cross/same site..

      Delete
    2. Same-site means that all scripts which executing at the context of the site's origin (if any) weren't came from 3rd party site controlled by an attacker.

      Perhaps, you're slightly confused in terms of "weakness", "threat", "vulnerability" and "attack".

      I'll try to explain...

      When some code writes something into HTTP response using an input data, we always have a threat of "integrity violation of HTTP-response". It exists regardless to the concrete way of input or output data handling. In the same way there is a weakness of the "usage of string concatenation for generation output data from input data". Assume we have a next code fragment (C#, ASP.NET):

      Response.Write("Your name is: " + Request["Name"]);

      It's vulnerable not only to the cross-site scripting attacks. Here we have a case when a specific threat met a specific weakness (see above for their definitions) and this creates the vulnerability of "injection into the body of HTTP response". If hypothetical attacker has the ability to exploit it, then he has a set of possible attacks. Using different vectors he implements various attacks (only some of them):

      ?Name=<script>alert(/XSS/)</script> - XSS (because this vector contains script which will executed at the context of site's origin -> SOP bypass #1)

      as derivative of previous vector:
      ?Name=<form name="CSRFForm" action="URL" method="post" enctype="application/x-www-form-urlencoded"><input type=hidden name="NAME" value="VALUE"></form><script>document.CSRFForm.submit();</script> - CSRF through XSS (SOP bypass #1 by executing injected script and SOP bypass #2 by sending POST-request to server from it)

      another one:
      ?Name=<script>document.write('<div style="position:fixed; left:0; top:0, width:100%; height:100%; z-index:999;"><!-- Fake login form --></div>') - Content Spoofing through XSS (all the same SOP bypass #1)

      but:
      <div style="position:fixed; left:0; top:0, width:100%; height:100%; z-index:999;"><!-- Fake login form --></div> - pure Content Spoofing (no any SOP bypass)

      In other words: term "attack" means what attacker actually does in limits of concrete vulnerability (pair of threat and weakness). Not what he 'wants' or what he 'can'.

      Thus, what is the "weakness", "threat", "vulnerability" and "attack" in your example? =/

      Delete
    3. I know about these terms, I read your great article before (http://habrahabr.ru/post/149152/)

      In my example attack is CSRF through content spoofing, w/o actual scripting from attacker's side. To keep it simple I called it XSS

      Delete
    4. Ok, thnx)

      BTW reusing functionality of predefined scripts at particular frameworks (what I called 'same-site scripting') seems to be an interesting direction for further researches.

      Delete
    5. Yes, it seems like a prospective CSP bypass. With complex structures of DOM elements you can change JS variables and eventually make something bad.
      Interesting trick imo - http://homakov.blogspot.com.es/2013/04/how-frames-can-mess-with-parents.html

      Delete
  3. Another cool CSP bypass is JSONP
    script src="/data.js?callback=alert(0);//"
    doesn't work for Chrome XSS Auditor

    ReplyDelete