As mentioned above the web browser would send the appropriate cookies for a website in the HTTP header. To do so, the browser follows the same-origin policy to determine which cookies to send when a website is being opened in the web browser of the client. The same-origin policy is also used by the DOM (document object model) to determine if a website can access the domain of another website (for example if a webpage host another site in an IFRAME). But there is a difference on how same-origin policy is understood by the browser DOM and while working with cookies.
Let’s take the example of this website, http://www.nerdbackbone.blog/page1.html?s=something. This address can be represented as – scheme://domain:port/path?param.
Same-origin policy for DOM
Let’s suppose as website page wats to open another webpage in an IFRAME. The parent webpage can perform some important functions on the browser such as it can read its cookies, it can redirect the browser to a different website/webpage. It can also change the location of its child IFRAME, to redirect to a different website. The browser safeguards the website the user using the same-origin policy. The DOM implements the same-origin policy with three of the properties, i.e. scheme, domain, and port. The table below describes if the browser would allow DOM access from one website to another:
Let’s assume the cookie is set by the following page – http://www.nerdbackbone.blog/page1.html. The browser would determine the following site as the same website, as they have the same scheme, domain, and port.
|Website address||Access Behavior|
|http://nerdbackbone.blog/other.html||Not Allowed (missing www)|
Same-origin policy for Cookies
This is used by the browser to determine which cookies need to be included in the HTTP header when the website is called. The browser implements the same-origin policy for cookies with these of the three properties, i.e. scheme, domain, and path. The table below describes if the browser would send the cookies when the website is accessed:
Let’s assume the cookie is set by the following page – http://www.nerdbackbone.blog/page1.html. The browser would send the cookie if it has the same scheme, domain, and path.
|Website address||Sent Behavior|
|http://www.nerdbackbone.blog:81/page1.html||Sent (port ignored)|
|http://nerdbackbone.blog/page1.html||Not Sent (missing www)|
Additional attributes of Cookies
Cookies have some additional attributes besides the scheme, domain, port, and path. They are:
- Secure: The “Secure” cookie attribute instructs web browsers to only send the cookie through an encrypted HTTPS (SSL/TLS) connection. It ensures that an attacker cannot simply capture the cookie values from web browser traffic.
- Expires and MaxAge: Sets the expiry date of the cookie, wherein the browser would delete on that date. Marking these fields makes the cookie a persistent cookie, as opposed to a session (temporary) cookie.
- HttpOnly: The “HttpOnly” cookie attribute instructs web browsers not to allow scripts an ability to access the cookies via the DOM document.cookie object. Without this, the cookie is susceptible to be stolen through an XSS.
- SameSite: This allows a server to define a cookie attribute making it impossible to the browser send this cookie along with cross-site requests. The main goal is mitigating the risk of cross-origin information leakage and provides some protection against cross-site request forgery attacks.
So, the scoping attributes of a cookie are the domain and path. So, if two cookies are set by login.site.com with the following attributes –
- Cookie 1: name=userid, value=user1,domain=site.com, path=/,secure
- Cookie 2: name=userid, value=user2,domain=.site.com, path=/,non-secure
When a user accesses the following pages:
- https://account.site.com = Cookie 2 is sent
- http://login.site.com = Cookie 2 is sent
- https://login.site.com = Cookie 1 and Cookie 2 is sent
- http://someothersite.com = No cookies are sent
But keep in mind, the path attribute is for the browser to decide the cookies to send, and not for DOM. So, if there is an XSS vulnerability in the site, the attacker can execute a script in a page of the same domain to read the cookies of all the pages (path) the domain. That is, if a cookie is set by http://site.com/page1.html with the path as page1.html, the script would return cookies for all paths under http://site.com/* (as the path is ignored by DOM).
This can be mitigated by setting the cookie with the HttpOnly flag (explained below), in which an XSS vulnerability cannot take advantage of this.
Few General problems with Cookies
Server Nevers sees anything besides the cookie’s data
That is, the server only sees the Name=Value data, and the browser strips away all attributes of the cookies before sending it through the HTTP header. For example, User1 logins to login.site.com, and the website sets a cookie for *.site.com. Then User1 visit attacker.site.com, which set a new cookie for *.site.com, overwriting the original cookie, with bad data. When User1 visits login.site.com, it gets the attacker cookie, and it has no way of knowing that this is not the original cookie. So, cookies need to be scoped properly to prevent leaking.
Secure cookies are not secure
Suppose, User1 visits an HTTPS version of a website which sets a Secure and HttpOnly cookie. Then the User1 later visits the HTTP version of the website (a lot of websites run as both HTTP and HTTPS), whose traffic is intercepted by an attacker, he injects a Set-Cookie command in the response. This would overwrite the secure cookie, and the server would never know. So, an HTTPS website should never leave an HTTP endpoint accessible. If there is, it is a good idea to redirect to the HTTPS version when someone accesses the HTTP version.
Cookies have no integrity by default
The cookies are stored in the user machine and can be very easily tampered with. Anyone who has access to the machine can delete or edit the contents of the cookies. So, it is imperative to implement a checksum to the cookie. For example, in ASP.Net you can protect the cookie by encrypting it and adding integrity using the System.Web.Configuration.MachineKey.
Cross-Site Scripting (XSS)
This issue is further elevated if the website doesn’t handle session cookies properly, that is, they should always invalidate the cookie once the user logs out, or if a user changes their role from an anonymous user to an authenticated user, a new cookie should be issued and honored.
There are different mitigation for XSS, and in terms of cookies, the cookies can be set HttpOnly to ensure the DOM cannot read it, i.e. the document.cookie cannot read it.
Cross-Site Request Forgery (XSRF or CSRF)
XSRF is another form of attack that doesn’t try to steal the cookies but rather forces the user to send a valid cookie to the web page to perform an action of the attackers choice. This is how it works – the attacker can trick a user to click on a link or open a page which would perform an HTTP GET or POST. This is usually done through social engineering or by embedding these scripts/pages in emails, online forums etc.
Let us take an example of a scenario, where User1 is sending money to User2 through a bank web page. A valid request to the server could be http://awesome_bank.com/send_money?to=User2&amt=1000.
In the GET method, the attacker can trick a user to click on a link whose description might seem inconspicuous, but the actual link would be different. For example:
<a href="http://awesome_bank.com/send_money?to=Attacker&amt=1000">You won $1 million, click here to redeem it</a>
In the POST method, the attacker can send an HTML email or make the user visit a web page, which has the following code:
<form action="http://awesome_bank.com/send_money" method="POST">
<input type="hidden" name="to" value="Attacker"/>
<input type="hidden" name="amt" value="100000"/>
Since the original user is logged in when they performed these operations, the session cookie would be included in the HTTP header, and the web server would perform the operation successfully as it doesn’t know that the request actually originated outside its page.
There are several mitigations for this attack, but from the cookie perspective, the SameSite flag ensures that the cookies are only sent if the site is same as the one who set the cookie.