Analyzing Impact of WWW Subdomain on Cookie Security
This blog post provides an introduction to subdomains, why we use WWW and analyzes the impact of the WWW subdomain on cookie security. Then, it examines why we use WWW and how to set the domain attribute of cookies. The post includes two case studies and code samples.
Your Information will be kept private.
Your Information will be kept private.
With the release of Chrome 69, Google opted to hide the www and m subdomains from the address bar, claiming that they’re not used anymore and therefore don't need to be displayed in the address bar.
Is the www subdomain really as trivial as Google claims? This apparently tiny detail means a lot for cookies, which allow the stateless HTTP protocol to become more dynamic and user-friendly. In this article, we discuss the necessity of the www subdomain from the cookie security perspective and make a few recommendations.
A Short Introduction to Subdomains and Why We Use WWW
Today, HTTP – commonly referred to as the (world wide) web – has become the internet’s most popular protocol. Years ago, this wasn’t the case. The protocols used in a service were often specified as a subdomain, such as ftp.example.com, gopher.example.com, and mail.example.com.
There are various discussions about the necessity of the www subdomain. One aspect is the Same Origin Policy, which allows only web pages that are on the same domain to talk to one another. The www subdomain doesn't really affect this domain isolation though. This is because even if you share Second Level Domains (SLDs) with third-parties, such as ziyahan.example.com or mustafa.example.com (as is often the case with certain web hosts), they aren't permitted to access each other’s DOM or that of example.com regardless of the presence of www. However, if both ziyahan.example.com and example.com have pages that set the JavaScript's document.domain property to the value 'example.com', they can access each other's DOM.
The Domain Attribute of Cookies
Cookies, which began to be used in 1994, understand the concept of origin differently than the Same-origin Policy (SOP), which would be designed a year later. Cookies may contain domain, path, expire and name attributes, and flags like httpOnly, and secure.
Let's examine the domain attribute in detail. The domain attribute specifies the domain for which the cookie is valid and tells the browser to which websites it can be sent with the request. It is an optional value, and in case it’s left empty, the domain name that the cookie is set to will be used. If you use an IP address to access the website, you’ll see this IP address in the value.
Website A cannot set a cookie belonging website B, even if they specify the domain attribute accordingly. Due to security measures, such attempts are blocked in both server and client side. However, a cookie may be used in multiple subdomains belonging to the same domain. For instance, a cookie set for example.com, may be sent along with the requests sent to mail.example.com, calendar.example.com, crm.example.com. The process is completed by comparing the cookies’ domain and the hostname of the requested URL using the Tail Comparison method. This method compares the URLs from the end to the start (right to left), and the matching cookies are sent with the request.
This is how you set the domain attribute:
Set-Cookie: Scanner=Netsparker; domain=example.com
This table shows a list of possible domain fields and to which domains the cookies will be sent by the browser.
The Domain That Sets the Cookie | The Domains the Cookie will be Sent to | The Domains Cookie will not be sent to |
www.example.com | www.example.com *.www.example.com |
example.com art.example.com other.example.com |
art.example.com | art.example.com *.art.example.com |
example.com www.example.com other.example.com |
.example.com | example.com *.example.com |
As illustrated in the table, domains are very important in terms of cookie security, especially in the websites that have subdomains.
Before the cookie is sent with the request, the requested URL and the domain value of the cookies found in the browser memory (Cookie Jar) go through a comparison. The other criteria are checked only if the Tail Comparison results positively.
The different actions browsers take on this matter, the fact that the cookie domain isn’t grasped entirely, and the increasing trend of abandoning the use of www all add up to security breaches. We can illustrate this with an example.
Case Study of Setting Domain in Cookies
Let’s assume there are two accounts created on badsites.local:
- victim.badsites.local
- attacker.badsites.local
The users’ websites will be visible to those who visit these websites. If the user wants to make changes on their website, they have to login to badsites.local and make the necessary changes in the control panel.
The “victim” user logs in to their control panel. This is the HTTP request for logging in:
POST http://badsites.local/control.php HTTP/1.1
Host: badsites.local
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
username=victim&password=victim
The response from the server will have three forms depending on the domain value. We have to observe the reactions browsers give to these three different responses. The browsers used in this test are Chrome 69.0.3497.100, Internet Explorer 11, Mozilla Firefox 44.0.2, Edge 42.17134.1.0:
Case 1: Domain Value of the Cookie is Not Set
This is how a set-cookie header looks like if the domain parameter was not set.
HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=ock3keuidn0t24vrf4hkvtopm0; path=/;
The four major browsers react similarly to the missing domain parameter. Internet Explorer’s older versions (such as 11.0.10240.17443) add the cookie to all the requests sent to subdomains under badsites.local and cause a serious security breach.
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: tr,en-US;q=0.7,en;q=0.3
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: attacker.badsites.local
Cookie: PHPSESSID=ock3keuidn0t24vrf4hkvtopm0
If the victim, or any other user logged in to badsites.local, visits attacker.badsites.local, they will be able to take over the session on badsites.local via attacker.badsites.local.
Chrome, Edge, IE 11 (except some IE 11 versions that aren't up to date, i.e. 11.0.10240.17443) and Firefox browsers will not send the cookie with the requests for the subdomains.
Case 2: Cookie Domain Value is Set as badsites.local:
As you see the domain parameter is now set for the main domain basites.local.
HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=1fr54qg3j9rf77toohcpcsk8h0; path=/; domain=badsites.local;
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 66
Content-Type: text/html
IE, Edge, Chrome, and Firefox will add the cookie generated by badsites.local with the requests to attacker.badsites.local.
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: tr,en-US;q=0.7,en;q=0.3
Host: attacker.badsites.local
Pragma: no-cache
Cookie: PHPSESSID=1fr54qg3j9rf77toohcpcsk8h0
Case 3: Cookie Domain Value is Set as .badsites.local:
In this case the domain value was set to .badsites.local with a leading dot.
HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=q3a20kfes2u6fgvgsrspv0rpf0; path=/; domain=.badsites.local
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
IE, Edge, Chrome, and Firefox will add the cookie to requests made for attacker.badsites.local.
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: tr,en-US;q=0.7,en;q=0.3
Proxy-Connection: Keep-Alive
Host: attacker.badsites.local
Cookie: PHPSESSID=q3a20kfes2u6fgvgsrspv0rpf0
Importance of Cookies
In the cases we've examined, cookie domain values have to be set with great care. If the correct values aren’t supplied, your application might be at great risk. You can force the use of the www subdomain in all your domains. Doing so will allow the cookies to be added to www.badsites.local addresses even if you leave the domain value empty.
In situations where you have to host websites with multiple users, do not host potentially risky websites under your main domain. For example, websites that host multiple codes, like Github, host the processes under github.io instead of github.com.
Further Reading
The definitive guide to cookie domains and why a www-prefix makes your website safer