Subdomain Boxing

Introduction

Subdomain boxing is a technique for overcoming XSS (Cross-Site Scripting) and CSRF (Cross-Site Request Forgery) vulnerabilities.

Basics

Cookies
  • A cookie is included with every request to the domain on which it was defined—regardless of the origin of the page issuing the request.
  • A cookie can be set as Secure, meaning that it will only be sent by the browser over HTTPS.
  • A cookie can be set as HttpOnly, which means that it cannot be accessed by Javascript (if an application does not set this, then javascript running in the page can access cookies, meaning that XSS javascript could send the cookies elsewhere).
  • If the domain for a cookie is set to .mydomain.com, it will be sent with requests to any subdomain at mydomain.com.
  • Cookies should be signed by the server in order prevent them from being altered by anyone other than the server (this doesn't prevent anyone from reading the contents of the cookies, just from anyone tampering with them; the secret used to sign cookies in Rails is in config/initializers/secret_token.rb).

Same Origin Policy
  • By default, browsers prevent javascript from making requests except to the domain at which the current page is displayed (this prevents javascript from reading data from other origins, but does not prevent javascript from sending data to other origins—for example, a form in an iframe may be submitted using javascript—not an ajax POST, but a form submission that causes the iframe to refresh, but the user doesn't notice because the iframe is hidden).
  • Subdomains count as different origins.
  • HTTP and HTTPS versions of the same page count as different origins.
  • Cross-Origin Resource Sharing (CORS) is a mechanism by which servers can tell the browser to allow requests from javascript running in pages hosted on other domains.
  • Communication with iframes abides by the same rules, though there are mechanisms for allowing cross origin communication here as well (postMessage, sandbox warning: if nothing else, I hope what I say tonight shows you that you need to be extremely careful with such things!)

XSS (Cross-Site Scripting)

XSS is when javascript that you have not authorized runs on your site. It executes in the browser when a user loads a compromised page from your site. The javascript can do anything against the current domain that the currently authenticated user can do.

For example, let's say you are the site admin, and you are signed into your admin panel in a browser tab. In another browser tab, you are browsing pages on your site where someone has injected javascript. If the admin panel accepts requests from the same domain as the rest of the site, then the javascript can read anything that you can read through the admin panel and send that data off to another server.

And if you don't have separate sessions for your admin self and your non-admin self, and the compromised page you are on has any forms with your CSRF token (see below), then the javascript in that page can use that CSRF token to POST, PUT, or DELETE anything in the admin panel that you can even if your admin panel is only available on a separate subdomain from the rest of your site (because the Same Origin Policy only prevents javascript from reading from a different subdomain, but does nothing to prevent javascript from creating a form in an iframe and submitting that form, complete with your CSRF token, to a different domain).

CSRF (Cross-Site Request Forgery)

If an attacker can lure a visitor to a site running javascript that the attacker controls (XSS on a popular site?), then the attacker can issue requests from the visitor's browser. Since cookies are sent with every request, if the attacker issues commands against sites that the visitor is logged into, then apart from any other protection, those sites would interpret those commands as being made by the visitor.

The Same Origin Policy prevents the attacker from receiving any data back from the site, so the attacker is limited to attacks that rely on changing something on the server rather than retrieving something directly from the server.

To protect against CSRF, a site should require that a token be sent as an HTTP parameter with any request that modifies state on the server. This token is sent to the user's browser in a request header or rendered into the HTML when a user visits a page on that site. The token also exists in the session (in a cookie for apps that use cookies as the session store) for comparing against what is sent in the HTTP parameter.

Subdomains & CSRF Tokens

Egor Homakov (famous for a particular commit to Rails) discovered a way to hijack CSRF tokens in Webkit browsers on sites that enable user generated content to be displayed on subdomains of the main site (Github pages were susceptible to this, so they moved Github Pages to Github.io). It was this article, and Egor's proposed solution of page boxing that inspired subdomain boxing.

Subdomain Boxing

Subdomain Boxing is a technique for limiting XSS attacks and CSRF attacks to the resource that an attacker was already given privileges to modify. By displaying potentially dangerous content on its own subdomain, we get the Same Origin Policy working for us and preventing user-added javascript from reading other resources in our application. Since the CSRF token is made available to any of your scripts so that your scripts can modify the current page, we customize the CSRF token to each subdomain, thereby stopping the javascript from making POST, PUT, and DELETE calls to other parts of your app that are boxed to other subdomains.

[demo]

comments powered by Disqus
background
©2011 Kristina Servant. CC BY 2.0