Starting from Chrome 51, a new attribute SameSite has been introduced for browser cookie. This attribute is to prevent CSRF attack.
Cookie is normally used to store data exchanged between client and server. It frequently stores user login information. If a malicious website can forge a HTTP request with the valid third party website cookie, it may be called a CSRF attack.
For example, if a user logins to a bank website your-bank.com, the bank server responds a cookie:
Set-Cookie:id=a3fWa;
Later the user somehow visits malicious.com and there is a form on the website.
<form action="your-bank.com/transfer" method="POST">
...
</form>
Once the user is lured to submit the form, the bank website will receive a request to transfer amount with valid cookie containing the user login information. To prevent this kind of attack, normally a form should contain a hidden field with a random token to prove to server it's a real valid request.
<form action="your-bank.com/transfer" method="POST">
<input type="hidden" name="token" value="dad3weg34">
...
</form>
This type of cookie which is sent because of a third party website trigger is called third party cookie. Apart from CSRF attack, it can be used to track user as well.
For example, assume Facebook inserts an invisible image in a third party website with below code.
<img src="facebook.com" style="visibility:hidden;">
When the browser loads the page with above code, it will send a request to Facebook as the image src tag points to facebook.com, this request would normally contain some cookie containing the user information and website information. Hence Facebook could track user web history.
The SameSite attribute introduced by Chrome is to reduce security risk by restricting third party cookie. It can have three values:
- Strict
- Lax
- None
Strict as it means it will completely restrict third party cookie. When cross site accessing, it will not send cookie to another website in any circumstance. It will only send cookie when the target page and current page have the same origin.
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
This value is so strict which may bring bad user experience. For example, if the current page contains a link to Github, in this case the user will not be in logged in state if the user clicks the link and visits Github.
Instead Lax is a bit less strict, it will not send third party cookie in most cases unless the target link is a GET request.
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
It has three scenarios: link, preload request and GET form.
Request type | Example | Normal case | Lax case |
Link | <a href="..."></a> |
Send cookie | Send cookie |
Preload request | <link rel="prerender" href="..."/> |
Send cookie | Send cookie |
GET form | <form method="GET" action="..."> |
Send cookie | Send cookie |
POST form | <form method="POST" action="..."> | Send cookie | None |
iframe | <iframe src="..."></iframe> | Send cookie | None |
AJAX | $.get("...") |
Send cookie | None |
Image | <img src="..."> |
Send cookie | None |
When Strict or Lax is set, most of the CSRF attacks can be prevented, but it requires the browser to support this attribute.
Lax will be the default value in Chrome 76 and the user needs to set it to None if s/he wants to explicitly turn off the SameSite attribute. However, it must come along with the Secure attribute so that the cookie can only be sent when using HTTPS protocol in this case. Otherwise it will have no effect.
Below setting will not work.
Set-Cookie: widget_session=abc123; SameSite=None
Below setting works.
Set-Cookie: widget_session=abc123; SameSite=None; Secure
Reference: