What are SameSite cookies?
As a logged-in customer of bank.com what would happen if you visited this page hosted on evil.com?
<body onload="document.form.submit()">
<form name="form" method="post" action="//bank.com:2000/transfer" target="iframe">
<input type="text" name="amount" value="1000000">
<input type="text" name="toAccount" value="188267171926">
</form>
<iframe name="iframe"></iframe>
</body>
The form will be submitted immediately to bank.com and processed successfully if bank.com does not use a cross-site request forgery (CSRF) token for protection against CSRF attacks.
In case you didn't know, browsers send the cookies to the "owner website" (the one which set them) whenever any request is made to it, irrespective of whether the request originated from the "owner website" or any other website and irrespective of whether the request is for a webpage or CSS file or a JavaScript file or any other resource.
"So, would this attack work on any website; like my banking website, Google, Facebook, Twitter etc.,?"
It would, if they did not use SameSite cookies for authorization. However, all security-aware websites use SameSite cookies, so it would actually not work on those websites, unless they forget to use SameSite cookies someday.
"So, what are SameSite cookies?"
SameSite cookies are cookies that were created with the SameSite
attribute.
How to set the SameSite attribute#
Cookies are created using the Set-Cookie
HTTP response header:
Set-Cookie: sid=dGhpcyBpcyB0aGUgZ3JhdGV0cyBzb25n
To set the SameSite
attribute, terminate the cookie value with a ";
" and add the attribute value.
Set-Cookie: sid=dGhpcyBpcyB0aGUgZ3JhdGV0cyBzb25n; SameSite=Strict
What happens when the SameSite attribute is set?#
The SameSite
cookie attribute can be set to either Strict
or Lax
. Let's see how they affect the behavior of cookies.
Strict#
If the SameSite
attribute is set to Strict
, the cookie will not be sent to the "owner website" if the request originate from a different website.
"Why not have this behavior by default for all cookies?"
Imagine clicking on a "Share it on Twitter" button or a link to a GitHub repository or a YouTube video. Since no cookies will be sent along with these requests, you will be treated like a user who has not logged in, even though you may actually be logged in.
So, in the highly connected and social Web, SameSite
set to Strict
is not ideal for all cookies.
However, using a cookie with SameSite
set to Strict
for state altering requests (create, delete, update) to endpoints can greatly increase the security of your website.
For websites requiring absolutely high security levels like banking websites setting SameSite
to Strict
is the right choice.
Lax#
Cookies with the SameSite
attribute set to Lax
will only be sent along with GET requests originating from forms, links, document.location
change, http-equiv refresh
and other top level navigations, from other websites.
They will not be sent from iframes or when other websites load files (JavaScript, CSS, images, etc.,) from the "owner website". Same goes for JavaScript initiated requests using XMLHttpRequest
or fetch
- not even for GET requests in these cases.
Lax
cookies are great for maintaining the session across other websites.
Since state-altering operations are ideally implemented using POST, PUT, and DELETE HTTP methods, sending some of the "trusted cookies" along with GET requests from external websites can be considered safe.
However, if your application or the web framework does any of the following, the safety provided by lax SameSite cookies are undone and your application could become vulnerable to CSRF attacks.
- Implementing state altering requests using GET requests.
- Supporting additional interface of CRUD operations using GET method and its parameters, on top of the standard interface using POST, PUT, and DELETE methods.
- HTTP method override using a parameter in the request URL, something like
method=POST
.
Which cookies should be set to SameSite?#
Session cookies should be set to Lax
. This cookie is responsible for determing whether a user is logged in on not.
If you want to restrict state-altering operations only for requests coming from your website, you can create an authorization cookie with SameSite
set to Strict
, and check the presence of this cookie to allow the operation or not.
If your web application doesn't use the GET method for implementing state-altering operations, lax SameSite cookies should be enough for both authentication and authorization.
If you are a high security organization that doesn't care about any referred requests, strict SameSite cookies are what you should be using.
Summary#
Cookies without the SameSite
attribute will be submitted to the "owner website" even when requests originate from other websites. Unless that's what you want (for analytics, tracking etc.,) make sure to set the SameSite
attribute to your cookies.
Strict SameSite cookies will be send to the "owner website" only if the request originated from itself.
Lax SameSite cookies will be send to the "owner website" from other websites only in GET requests originating from a top level navigation to the "owner website".