Separating Subdomains From Third-Party Hosted WWW Domains

Setting cookies on domains that have multiple subdomains can pose security risks if it is implemented incorrectly. An attacker who gains access to a particular domain can conduct a session fixation attack and hijack users’ sessions on its subdomains. To prevent attacks, there are a few security attributes and best-practices. In this article, we explain how to separate subdomains from a third-party controlled www domain.

The Purpose of Cookies on Websites with Multiple Domains

Let's say you have the domain example.test . When setting cookies on it, you use the domain attribute .example.test as shown below:

Set-Cookie: SetByCookieDotExampleDotTest=yes; domain=.example.test; path=/;

This ensures that the cookie will be sent along with all the requests including *.example.test subdomains such as cookie.example.test and www.example.test. This is why browsers use the tail comparison method when determining which cookie should be sent along with the request. The tail comparison method compares the URLs from the end to the start (right to left).

However, since the site under our WWW subdomain is hosted by a third party, we have a slight problem. Being under the same second level domain (SLD) with a third party means that if an attacker gets access to the third party, it can affect the rest of the sites under the same SLD. Ideally, we would like to separate our third party hosted domain (WWW) from others.

At first sight, it seems like there’s no way to do this. However, the sandbox attribute of the Content Security Policy (CSP) header allows us to address the problem. The sandbox attribute generates a sandbox for the requested resource similar to the <iframe> sandbox attribute. It applies restrictions to the actions of a page such as preventing popups, preventing the execution of plugins and scripts, and enforcing a Same-origin Policy or a unique policy.

Demonstration of the Sandbox Attribute

Let’s take a closer look at the sandbox attribute.

This is the HTTP response you get when you visit cookie.example.test:

HTTP/1.1 200 OK

Set-Cookie: SetByCookieDotExampleDotTest=yes; domain=.example.test; path=/;

Whenever you visit foo.example.test or bar.example.test or any *.example.test domain, the browser sends a request like this:

GET / HTTP/1.

Host: foo.example.test

Cookie: SetByCookieDotExampleDotTest=yes;



GET / HTTP/1.

Host: bar.example.test

Cookie: SetByCookieDotExampleDotTest=yes;



GET / HTTP/1.

Host: www.example.test

Cookie: SetByCookieDotExampleDotTest=yes;

As you can see, the browser will send the cookie along with the three requests.

However we don’t want www.example.test to be able to read the cookies that are set for the other domains on *.example.test. If we return the CSP sandbox attribute in the response of www.example.test, we’ll prevent the www subdomain from reading the cookies set for other subdomains. Here’s a sample implementation of the sandbox attribute:

HTTP/1.1 200 Generated

Content-Length: 316

Content-Type: text/html; charset=utf-8

Content-Security-Policy: sandbox allow-forms allow-scripts;



Hello www.example.test/



<script src="https://code.jquery.com/jquery-2.2.4.js"

integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI="

crossorigin="anonymous"></script>

<script>



$( document ).ready(function() {

console.log( "ready!" );

console.log(document.cookie);

});

</script>

For further information about the sandbox attribute of the Content Security Policy (CSP), see CSP: sandbox.

Advantages of the Content Security Policy Sandbox Attribute

This method can only prevent the WWW domain on the client-side from reading the cookie. If attackers take control of the server, they can access and abuse the cookies by executing server-side scripting codes, or by sniffing the requests that come to the server. They could also remove the CSP sandbox header.

Although it resembles the httpOnly cookie flag a little, the sandbox attribute has its unique advantages. For example, the httpOnly flag can prevent the WWW subdomain from reading the cookies, but it can’t prevent it from overriding the cookie and launching a session fixation attack if the conditions are met.

Two domains can access each others’ DOMs if they both set their document.domain to their main domain, i.e. their Second Level Domain (SLD). For example, if both foo.example.test and bar.example.test set their document.domain attribute to example.test they can access each others’ DOMs.

A malicious user who takes control of www.example.test can set its document.domain to example.test to access the DOM of both foo.example.test and bar.example.test. Setting the httpOnly flag on the cookie cannot prevent this attack from taking place. However, using the sandbox attribute on the CSP header can help prevent the WWW domain from changing or setting document.domain to any value, blocking the access to the document.domain property entirely.

Further Information

Content Security Policy is a relatively new concept in client-side security. The opportunities it serves deserve interests. For more information about CSP, see our blog post Content Security Policy, that explains in more detail how to specify the content that should be loaded in web applications.