XSRF Prevention with SameSite

The SameSite directive can be used to prevent XSRF attacks. Let's see how.

We'll cover the following

Introduction to SameSite #

We now have a very strong defense against XSRF—using an anti-XSRF hidden form input on all state-modifying requests. But that defense requires ongoing diligence. We’re never done applying it. We need to reapply this defense every time we add a new state-modifying request to our web application (which will happen pretty often during active development of a web application).

It would be nice if we could layer on a one-time effort to help lessen the impact if we ever forget to be diligent in the future. That is the idea behind SameSite cookies. Let’s take a look at this defense, how it helps, and what its limitations are.

Suppose we are building a web application that uses a cookie called SessionId to authenticate logged-in users. Normally, this cookie would be created by an HTTP response that includes a Set-Cookie header like this:

Set-Cookie: SessionId=sfVZ1yx68LD51I;

As we saw in the previous section on XSRF, if this cookie is the session cookie for our web application, it would then be sent on every request to our application, regardless of what site originated the request. Wouldn’t it be nice if we could tell browsers to only send that cookie for requests that originated from our site? That’s the idea behind SameSite.

With SameSite, the part of the response that sets the cookie would look like:

Set-Cookie: SessionId=sfVZ1yx68LD51I; `SameSite`=Strict;

or

Set-Cookie: SessionId=sfVZ1yx68LD51I; `SameSite`=Lax;

To understand this defense, we first need to understand a little bit of HTTP trivia. The HTTP specification defines “safe” and “unsafe” requests in Section 4.2.1 of RFC7231. Safe requests use the GET, HEAD, OPTIONS, or TRACE methods. Unsafe requests use any of the other HTTP methods, including, most notably, POST requests. This distinction is there because the safe methods shouldn’t change state on the server; only the unsafe ones should be used to modify state. It’s the unsafe ones that we’re concerned with when preventing XSRF.

Adding SameSite=Strict to a cookie definition tells a browser to never send that cookie for any request to our site unless the request originated from our site. That sounds good in practice, but it’s often not what we want. With SameSite=Strict, other sites won’t be able to link successfully to our web application because the initial request to our web application won’t include the SessionId cookie since it originated from another site. If a user clicks on a link from another website to our web application, that first request would not include the SessionId cookie, so the user would probably be prompted to log in, even if they had already logged in. If you know that you don’t need to support other sites linking to your web application, this would be an appropriate choice.

More often, what you want is to set SameSite=Lax. By doing this, all safe requests will send the cookie, even if the request originates from another site. This way, the initial link from an external site to our web application will send the SessionId cookie since clicking on the link will result in a GET request. But a malicious site that wants to exploit XSRF by constructing a form and getting a user to submit a POST request would fail because the SameSite attribute on the SessionId cookie wouldn’t get sent because the request originated on another site.

So the addition of the SameSite attribute on our session cookie raises the bar for attackers in the event that we forget to implement XSRF defense in a new page in the future. Instead of being able to exploit the vulnerability by merely getting a logged-in user to browse to a website that the attacker controls, the attacker would need to find a DOM injection or XSS vulnerability in our web application in order to exploit the lack of XSRF defense. Pretty cool. Now what are the limitations of this defense? In describing the benefits of SameSite, we touched on the first limitation. SameSite doesn’t protect you if your site is vulnerable to DOM injection or XSS. Put another way, if your site is dynamic enough to allow an attacker to submit HTML to be viewed by other users, then SameSite won’t defend against XSRF attacks launched from within your own web application because all of the HTML and JavaScript is coming from the same site. It would still stop XSRF attacks initiated from other sites.

A second limitation is that the SameSite session cookie defense is dependent on support in the browser. Fortunately, it is widely supported.

Finally, SameSite doesn’t protect you if you allow safe methods to modify state. So if your website creates, updates, or deletes objects in your web application via safe methods, then SameSite will not protect you if you forget XSRF defenses.


In the next lesson, we’ll study some ways that misconfiguration can leave your system vulnerable.

Get hands-on with 1200+ tech skills courses.