Will same-site cookies be sufficent protection against CSRF and XSS?
First, a definition from Chrome:
Same-site cookies (née "First-Party-Only" (née "First-Party")) allow servers to mitigate the risk of CSRF and information leakage attacks by asserting that a particular cookie should only be sent with requests initiated from the same registrable domain.
So what does this protect against?
Same-site cookies can effectively prevent CSRF attacks. Why?
If you set the session cookie as same site, it will only be sent if a request emanates from your site. So a standard CSRF attack where the attacker lures the victim to the site
http://malicious.com that posts a request to
http://bank.com/transfer.php?amount=10000&receiver=evil_hacker will not work. Since
malicious.com is not the same origin as
bank.com, the browser will not send the session cookie, and
transfer.php will execute as if the victim was not logged in.
This is very similar to how setting a
X-Csrf-Token HTTP header protects you from CSRF - again there is something that is only sent if the request emanates from your domain. The same-site property turns your session cookie into a CSRF-token.
So problem solved? Well, sort of. There are some caveats:
- This will only work for browsers that implement this feature. So far, very few do. Unless you want to throw everybody who uses a slightly older browser under the bus, you will still need to implement an old fashioned CSRF-token.
- If you need more fine-grained control, this will not be enough. If you run a system that displays untrusted user content, like a forum, you don't want requests originating from user posts to be treated as valid. If someone posts a link to
http://myforum.com/?action=delete_everythingyou don't want that to delete anything just because a user clicks it. With a traditional CSRF-token, you can control exactly when it is used. With a same-site cookie, you can not.
- The same old caveats as for old fashioned CSRF protections still apply. If you have an XSS vulnerability, no CSRF protection in this world will save you.
With that said, the same-site cookie is still a good thing that should be used together with traditional defenses as defense in depth.
XSS and XSSI?
The same-site cookie does nothing to protect you from ordinary XSS attacks. If a hacker manages to fool your site to echo out script from the URL on your site, it will be executed as coming from your origin (after all, it is), and thus session cookies will still be sent with all requests the injected script makes to your domain.
If you read the quote in your post carefully, you will see it says XSSI with an I at the end, and not XSS. The I stands for inclusion, and XSSI is related to, but different from, XSS. Here is a good explanation of XSSI and how it differs from XSS:
XSSI is a form of XSS that takes advantage of the fact that browsers don't prevent webpages from including resources like images and scripts, which are hosted on other domains and servers. [...] For example, if Bank ABC's site has a script that reads a user's private account information, a hacker could include that script in their own malicious site (www.fraudulentbank.com) to pull information from Bank ABC's servers whenever a client of Bank ABC visits the hacker's site.
Same-site cookies protects you from XSSI, since a session cookie would not be sent with the request for the script and it would thus not return any sensitive information. However, for ordinary XSS it makes no difference.
It depends what browsers you want to support and how your site is currently set up.
If you are strictly supporting only browsers that support the feature then it should be sufficient if you're willing to either:
- Not send cookies with top-level navigation (this is quite restrictive as you can't link to logged-in pages externally)
- Ensure no operations use
GET(or any safe method) to perform an operation, otherwise you open yourself up to link attacks like in the previous answer
If you can live without top-level navigation to logged in pages from external sites then
SameSite: 'strict' might be suitable, this option makes the given cookie not sent with any request made cross-origin (including clicking links, etc).
If you need linking into logged-in pages from external sites then you need to ensure no observable changes will occur from a
GET (or any safe method) to the server and should use
SameSite: 'lax' instead. If you can ensure this constraint then even user-submitted links should be safe (from CRSF attacks anyway).
Ensuring either of these constraints is probably not trivial in an existing code-base (in addition to the modern browser requirement) so I wouldn't recommend removing CSRF tokens if you're already using them, as a lot of places still abuse
GET for triggering operations.
If you're starting a new project and aren't planning on supporting any browsers that don't support the feature it's probably worth considering as it is basically just a single line of code, just make sure you're aware of both the
'strict' modes and what restrictions you'll need to follow with both of them.
SameSite: 'strict': If you're using
SameSite: 'strict' and a user clicks an external link into a restricted part of the site then could show a splash screen asking if they want to proceed. I would highly recommend this if the resources aren't intended to be linked externally in which case a link is likely to be an attack/trick.
By having such a splash screen if the user does choose to proceed then they still won't need to login again because clicking proceed on your site will send
SameSite-cookies because it is indeed the same origin.
If you want to the redirection to happen automatically you could also just add a
Refresh: 0 header for pages that you know are safe (which is also a great opportunity to check if a given page is actually safe to be externally linked, if not fall back to splash screen mentioned above). The major downside of this vs
SameSite: 'lax' is that you wind up repeating the navigation twice.