-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[gear] Make csrf cookie samesite=strict #14180
Conversation
@@ -98,6 +96,5 @@ async def render_template( | |||
context['csrf_token'] = csrf_token | |||
|
|||
response = aiohttp_jinja2.render_template(file, request, context) | |||
domain = cookie_domain or deploy_config._domain | |||
response.set_cookie('_csrf', csrf_token, domain=domain, secure=True, httponly=True) | |||
response.set_cookie('_csrf', csrf_token, secure=True, httponly=True, samesite='strict') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I feel like I'm now a bit confused about our previous conversation.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#strict
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#domaindomain-value
It sounds like Strict is necessary for CSRF to work: otherwise I could put this on an evil website (excuse my totally invented HTML, I didn't bother to look up the right syntax and attribute names) and trick people into cancelling their batches, right?
<form method="POST" url="https://batch.hail.is/batches/123/cancel">
<button>
</form>
In particular, do we have any CSRF protection at all right now?
I agree we should remove the domain attribute:
Only the current domain can be set as the value, or a domain of a higher order, unless it is a public suffix. Setting the domain will make the cookie available to it, as well as to all its subdomains.
If omitted, this attribute defaults to the host of the current document URL, not including subdomains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The server compares the cookie value to a value in the request (hidden value in the form), which means that in order to create a malicious form the evil site would need to know the value of the cookie which it can't because it is not the same origin (assuming they have not achieved the ability to set a cookie on our domain in which case signing our cookies would help)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
Currently, the
_csrf
cookie is made available to all subdomains of.hail.is
. This means that if I first visitbatch.hail.is
I get a_csrf
cookie set for.hail.is
. That cookie is then reused if I visitci.hail.is
. Even more awkward, the same value of the cookie will get reused if I then visitbatch.azure.hail.is
. This isn't that big of a deal, these can all be considered part of the same application that the hail team delivers and secures, but it is very little work to set stricter bounds on where this cookie is sent. By removing thedomain
attribute and usingsamesite='strict'
, the cookie's domain will be set by the browser to the domain of the request whose response included theSet-Cookie
header, e.g.batch.hail.is
orinternal.hail.is
.Strict
mode then ensures that the cookie will only be sent to that exact domain, meaning that each application is guaranteed to receive the_csrf
token that it itself delivered, and a_csrf
token from CI cannot be used to take actions against Batch.This should not have an adverse impact on existing users' browser sessions. In
render_template
we preserve the value of an existing_csrf
cookie so this change should do the following:.hail.is
)_csrf
cookieSet-Cookie
header with a new_csrf
cookie for strictly thebatch.hail.is
domain but with the same token value as the original_csrf
cookie