SameSite Cookies

samesite

The introduction of the SameSite cookie attribute is described as allowing us to restrict a cookie in a same-site context.

For example, for my site www.nurettinabaci.org and “<any-subdomain>.nurettinabaci.org” domain is part of the nurettinabaci.org. If the user is on www.nurettinabaci.org and requests an image from static.nurettinabaci.org that’s a same-site request.

However, in services like github.io, if the user is on your-project.github.io and requests an image from my-project.github.io, it becomes a cross-site request.

The SameSite attribute is defined in RFC6265bis as follows:

A “SameSite” attribute which allows servers to assert that a cookie ought not to be sent along with cross-site requests. This assertion allows user agents to mitigate the risk of cross-origin information leakage, and provides some protection against cross-site request forgery attacks.

For example, you came to this site months ago and issued a session cookie and it has been stored in your browser. Months later you’ve come to this blog post directly from the Google search, not through navigating the listing page, in this case, it’s a cross-site request. If I tweak the SameSite attribute of user session cookies then the browser will decide to include or not the cookie into this cross-site originated request.

SameSite context

The concept of SameSite defines a site as a combination of a top-level domain and one additional domain level.

Request FromToDifference Samesite?
http://www.nurettinabaci.orghttps://www.nurettinabaci.orgSchemeNo
http://media.nurettinabaci.orghttp://admin.nurettinabaci.orgSubdomain (TLD+2)Yes

Site vs Origin

The contrast between a site and an origin lies in their respective scopes. While a site encompasses multiple domain names, an origin is confined to a single domain. Although these concepts share a close relationship, it is crucial to avoid interchanging the terms, as doing so can lead to significant security consequences.

For two URLs to be classified as having the same origin, they must possess identical schemes, domain names, and ports. It is worth noting that the port is frequently inferred based on the scheme employed.

As exemplified in this instance, the term “site” possesses a broader scope, considering solely the scheme and the final segment of the domain name. It is crucial to acknowledge that, as a result, a cross-origin request can fall under the same-site category, but not vice versa.

Request FromToDifference Samesite?Sameorigin?
http://www.python.orghttp://www.python.orgYesYes
http://www.python.comhttps://www.python.orgSchemeNoNo
http://www.python.comhttps://docs.python.orgSubdomain (TLD+2)YesNo
http://www.python.comhttp://www.python.com:8080Port numberYesNo
http://www.python.comhttp://www.python.co.ukeTLDNoNo

It is important to understand that while a cross-origin request can still be considered same-site, the reverse is not true. This distinction carries significant weight, as it implies that any vulnerability enabling the execution of arbitrary JavaScript code can be exploited to circumvent site-based defenses on other domains associated with the same site. I have written this subsection solely to clarify the disparity between the terms “cross-site” and “cross-origin”. Only the cross-site term applies to the SameSite context.

Usage

Prior to the introduction of the SameSite mechanism, browsers would send cookies in every request to the issuing domain, regardless of whether the request originated from an unrelated third-party website. SameSite operates by empowering browsers and website owners to restrict which cross-site requests, if any, should include specific cookies. This serves to minimize users’ vulnerability to Cross-Site Request Forgery (CSRF) attacks, which exploit the victim’s browser to initiate malicious actions on the compromised website. Given that these requests typically rely on a cookie associated with the victim’s authenticated session, the attack will fail if the browser does not include this crucial component.

Developers can manually configure a restriction level for each cookie they set, giving them more control over the way these cookies are used. To achieve this on your server, simply include the SameSite attribute in the Set-Cookie response header, alongside the desired value, as exemplified below:

Set-Cookie: sessionid=asdfasdfasdfasdf; SameSite=Strict

All major browsers currently support the following three SameSite restriction levels:

Strict: Cookie will be prevented from being sent in any cross-site originated requests. This becomes very critical for banking or similar services. To hinder CSRF attackers from hacking into your bank account banking websites use this option. If our session cookie of the banking website is marked as SameSite=Strict then the banking website will act like we’re not logged in yet and hackers won’t be able to transfer money with a cross-site forgery.

On the other hand, an ecommerce site issued a discount and emails to the customers with a fancy button with a link inside saying “%80 discount”. If users click on the button and follow the link, they want the discount to be applied right away to their basket. Strict is the most secure option but it can negatively affect the user experience. In this position, Lax comes in with some security.

Lax: The cookie will only be sent if the request method is GET and the request is within the same top-level domain.

Set-Cookie: sessionid=9asdf0asdf9asdf0asdf; SameSite=Lax

For example, in another website, someone referred to the image I created above like this:

<p>The difference between site and origin</p>
<img src="http://www.nurettinabaci.org/wp-content/uploads/2023/06/image-2.png" />
<p>Read the <a href="http://www.nurettinabaci.org/2023/06/23/development/samesite-cookies/">article</a>.</p>

and the session cookie has been marked as SameSite=Lax. The cookie won’t be sent when the browser requests image-2.png. However, when the reader clicks and follows the link, this request will include sessionid cookie in the headers.

As you can see, the cookie is not included in background requests, such as those initiated by scripts, iframes, or references to images and other resources, in the case of “SameSite=Lax”.

Strict and Lax was to restrict the cookie access.

None: If a cookie is set with the SameSite=None attribute, this effectively disables SameSite restrictions altogether, regardless of the browser. As a result, browsers will send this cookie in all requests to the site that issued it, even those that were triggered by completely unrelated third-party sites. There are legitimate reasons for disabling SameSite, such as when the cookie is intended to be used from a third-party context and doesn’t grant the bearer access to any sensitive data or functionality.

Additionally, it is possible to omit the SameSite attribute entirely.

Chrome and other major web browsers will treat cookies without the new “SameSite=None; Secure” attribute as “SameSite=Lax,” limiting their usage to first-party contexts. (Note that the use of the Secure attribute is mandatory when “SameSite=None” is employed.)

Resources
SameSite cookies explained
SameSite Cookie Attribute: What It Is And Why It Matters
Bypassing SameSite cookie restrictions
Preventing CSRF with the same-site cookie attribute