Live data from Hacker News

A modern approach to preventing CSRF in Go

alexedwards.net

31–40 of 104 posts

Re: A modern approach to preventing CSRF in Go

#31
post #6

Are CSRF attacks that common nowadays though? Even if your app is used by the 5% of browsers that don’t set the Origin header the chances of that being exploited are even more miniscule. Besides, most webdevs reach for token-based auth libraries before even knowing how to set a cookie header.

Curious about that too. In a modern web-app I always set HttpOnly cookies to prevent them being exposed to anything JavaScript, and SameSite=strict. Especially the later should prevent CSRF.

Erratum: What I'm saying here only applies for cookies with the attribute SameSite=None so it's irrelevant here, see the comments below.

(Former CTF hobbyist here) You might be mixing up XSS and CSRF protections. Cookie protections are useful against XSS vulnerabilities because they make it harder for attackers to get a hold on user sessions (often mediated through cookies). It doesn't really help against CSRF attacks though. Say you visit attacker.com and it contains an auto-submitting form making a POST request to yourwebsite.com/delete-my-account. In that case, your cookies would be sent along and if no CSRF protection is there (origin checks, tokens, ...) your account might end up deleted. I know it doesn't answer the original question but hope it's useful information nonetheless!

Re: A modern approach to preventing CSRF in Go

#32
post #25

I deeply appreciate this thorough review of CSRF protection via headers. I've been looking into the topic to see if I can get rid of csrf tokens, and it seems like I can now - if I ignore/don't care about the 5% of browsers that don't support the required headers. It makes me wonder though - most browser APIs top out around 95% coverage on caniuse.com. What are these browsers/who are these people...? The modern web i…

From business perspective it makes a lot of sense to just drop that bottom 5%. Actually, many businesses support Chrome only, they don't even support Firefox. Technological counterargument though is that you should allow people to tinker and do weird shit. Once upon a time tech wasn't about maximizing stock value, it was about getting Russian game crack to work, and making Lora's boobs bigger. Allowing weird shit is…

Thanks for confirming. I don't know that it has to be framed as a "business perspective" though. I'm a solo dev for a non-profit project, so ignoring the 5% is just a matter of pragmatism.

I most defintiely do not care about tinkerers, and in fact would generally classify them as something akin to attackers. I just want to allow as many people to use the app as possible, while keeping things simple and secure.

Re: A modern approach to preventing CSRF in Go

#33
post #19

I would never rely on headers such as "Sec-Fetch-Site"; having security rely on client generated (correct) responses is just poor security modelling (don't trust the client). I'll stick to time bounded HMAC cookies, then you're not relying on client properly implementing any headers and it will work with any browser that supports cookies. And having TLS v1.3 should be a requirement; no HTTPS, no session, no auth, no…

CSRF is about preventing other websites from making requests to your page using the credentials (including cookies) stored in the browser. Cookies can't prevent CSRF, in fact they are the problem to be solved.

Somewhere auth needs to be done, somewhere, somehow, and some when. And this is done with cookies (be it CSRF, auth token, JWT, etc). There has to be some form of mechanism for a client to prove that a) it is the client it claims it is, and therefore b) it has the permission to request what it needs from the server.

And, the server shouldn't trust the client "trust me bro" style.

So, at the end of the day it doesn't matter whether it is a "rose by another name", i.e. it doesn't matter whether you call it a CSRF token, auth token, JWT, or whatever, it still needs to satisfy the following; a) the communication is secure (preferably encryption), b) the server can recognise the token when it sees it (headers (of which cookies are one type), etc), c) the server doesn't need to trust the client (it's easiest if the server creates the token, but it could also be a trusted OOB protocol like TOTP), and d) it identifies a given role (again it's easiest if it identifies a unique client (like a user or similar)).

So a name is just a name, but there needs to be a cookie or a cryptographically secure protocol to ensure that an untrusted client is who it says it is. Cookies are typically easier than crypto secure protocols. Frankly it doesn't really matter what you call it, what matters is that it works and is secure.

Re: A modern approach to preventing CSRF in Go

#34
post #29
post #17

Earlier quoted context omitted.

CSRF protects the user by not allowing random pages on the web using resources from a target website, without the user being aware of this. It only makes sense when serving people using browsers. It is not a defense against curl or skiddies.

To elaborate/clarify a bit, we defend against curl with normal auth, correct? Be it session cookies or whatever. That plus origin/Sec-Fetch-Site (and tls, secure cookies, hsts) should be reasonable secure, no?

indeed, you need some form of CSRF, but the Sec-Fetch-Site is primarily focused on keeping a browser secure, not the server. Having said that it's nice defence in depth for the server as well but not strictly required as far as the server is concerned.

Re: A modern approach to preventing CSRF in Go

#35
post #19

Earlier quoted context omitted.

CSRF is about preventing other websites from making requests to your page using the credentials (including cookies) stored in the browser. Cookies can't prevent CSRF, in fact they are the problem to be solved.

Somewhere auth needs to be done, somewhere, somehow, and some when. And this is done with cookies (be it CSRF, auth token, JWT, etc). There has to be some form of mechanism for a client to prove that a) it is the client it claims it is, and therefore b) it has the permission to request what it needs from the server. And, the server shouldn't trust the client "trust me bro" style. So, at the end of the day it doesn't…

I don't think this is accurate. As your parent comment said, Csrf defenses (tokens, origin/Sec-Fetch-Site) serve a different purpose from Auth token/jwt. The latter says that your browser is logged in as a user. The former says "the request actually came from a genuine action on your page, rather than pwned.com disguising a link to site.com/delete-account.

You're conflating the two types of Auth/Defense.

Re: A modern approach to preventing CSRF in Go

#37
post #29

Earlier quoted context omitted.

To elaborate/clarify a bit, we defend against curl with normal auth, correct? Be it session cookies or whatever. That plus origin/Sec-Fetch-Site (and tls, secure cookies, hsts) should be reasonable secure, no?

indeed, you need some form of CSRF, but the Sec-Fetch-Site is primarily focused on keeping a browser secure, not the server. Having said that it's nice defence in depth for the server as well but not strictly required as far as the server is concerned.

I'm confused. In my mind, you only really need to keep the server secure, as that's where the data is. Auth cookies and csrf protections (eg Sec-Fetch-Site) are both used towards protecting the server from invalid requests (not logged in, or not coming from your actual site).

What are you referring to when you talk about keeping the browser secure?

Re: A modern approach to preventing CSRF in Go

#38
post #28

Earlier quoted context omitted.

All the voting down but not a single comment as to why. The "Sec-Fetch-Site" primarily protects the browser against Javascript hijacking, but does little to nothing to protect the server. This is probably apocryphal, but Willie Sutton was asked why he kept robbing banks, he quipped "that's where the money is". Sure browser hacking occurs, but it's a means to an end because the server is where the juicy stuff is. So h…

I must be missing something. What does JavaScript have to do with this? My understanding is that csrf is about people getting tricked into clicking a link that makes, for example, a post request to another site/origin that makes an undesired mutation to their account. If the site/origin has some sort of Auth (eg session cookie), it'll get sent along with the request. If the Auth cookie doesn't exist (user isn't logge…

There's server security and there's client security. From what I've seen in these comments people are focused on the client security and are either a) ignoring server security, or b) don't understand server security.

But the server security is the primary security, because it's the one with the resources (in the money analogy it's the bank).

So yes, we do want to secure the client, but if the attacker has enough control of your computer to get your cookies then it's already game over. Like I said you can have time bounded CSRF tokens (be they cookies or whatever else, URL encoded, etc who cares) to prevent replay attacks. But at the end of the day if an attacker can get your cookies in real time you're done for, it's game over already. If they want to do a man in the middle attack (i.e. click on a fake "proxy" URL) then having the "secure" flag should be enough. If the server checks the cookie against the client's IP address, time, HMAC, other auth attributes, will then prevent the attack. If they attacker takes control of your end device, you've already lost.

Re: A modern approach to preventing CSRF in Go

#39

Earlier quoted context omitted.

Curious about that too. In a modern web-app I always set HttpOnly cookies to prevent them being exposed to anything JavaScript, and SameSite=strict. Especially the later should prevent CSRF.

Erratum: What I'm saying here only applies for cookies with the attribute SameSite=None so it's irrelevant here, see the comments below. (Former CTF hobbyist here) You might be mixing up XSS and CSRF protections. Cookie protections are useful against XSS vulnerabilities because they make it harder for attackers to get a hold on user sessions (often mediated through cookies). It doesn't really help against CSRF attack…

The SameSite cookie flag is effective against CSRF when you put it on your session cookie, it's one of its main use cases. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/... for more information.

SameSite=Lax (default for legacy sites in Chrome) will protect you against POST-based CSRF.

SameSite=Strict will also protect against GET-based CSRF (which shouldn't really exist as GET is not a safe method that should be allowed to trigger state changes, but in practice some applications do it). It does, however, also make it so users clicking a link to your page might not be logged in once they arrive unless you implement other measures.

In practice, SameSite=Lax is appropriate and just works for most sites. A notable exception are POST-based SAML SSO flows, which might require a SameSite=None cookie just for the login flow.

Re: A modern approach to preventing CSRF in Go

#40
post #19

Earlier quoted context omitted.

CSRF is about preventing other websites from making requests to your page using the credentials (including cookies) stored in the browser. Cookies can't prevent CSRF, in fact they are the problem to be solved.

Somewhere auth needs to be done, somewhere, somehow, and some when. And this is done with cookies (be it CSRF, auth token, JWT, etc). There has to be some form of mechanism for a client to prove that a) it is the client it claims it is, and therefore b) it has the permission to request what it needs from the server. And, the server shouldn't trust the client "trust me bro" style. So, at the end of the day it doesn't…

I don't understand what you are getting at. CSRF is not another name for auth. You always need auth, CSRF is a separate problem.

When the browser sends a request to your server, it includes all the cookies for your domain. Even if that request is coming from a or tag on a different website you don't control. A malicious website could create a form element that sends a request to yourdomain.com/api/delete-my-account and the browser would send along the auth cookie for yourdomain.com.

A cookie only proves that the browser is authorized to act on behalf of the user, not that the request came from your website. That's why you need some non-cookie way to prove the request came from your origin. That's what Sec-Fetch-Site is.

Post reply on HN