justinas/nosurf

Combining Session and CSRF cookie

xeoncross opened this issue · 3 comments

Background: The current system of open reads of the CSRF cookie by Javascript also means that valid CSRF tokens can be stolen and re-used infinitely(?) assuming 1) the route does not require auth/session data or 2) a valid session was also stolen.

Thought experiment: I'm contemplating changes to combine the two separate cookies (session and CSRF) into a single cookie. This would reduce the load on the randomness source and reduce bandwidth between the server and client.

Currently however, the CSRF is Javascript-readable which is an attack vector for the session. To prevent malicious client-side javascript from stealing the OTP CSRF token (and thereby knowing how to generate the true token to compare with it) two changes seem required:

  1. Main CSRF cookie token should be httpOnly, Strict, and Secure (HTTPS-only)
    by default: https://github.com/justinas/nosurf/blob/master/handler.go#L204
  2. Form/Header OTP+OTP(Token) should be hashed with server secret OTP+OTP(hash(secrete, token))

This means that if Javascript were to retrieve/steal the form/header token they would
be unable to construct the original HTTP-only cookie token for the session itself. (This is important if the CSRF cookie was also used as the session cookie)

This is a defense mechanism called "Double Submit Cookie" and OWASP recommends having them as separate cookies: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html

Also, there is no good protection against CSRF if you are XSS vulnerable as the request is coming from the same domain (and thus not cross-site).

Thanks, I wrote part of the "Double Submit Cookie" section actually. Sending two cookies helps the implementation be less prone to error, but isn't technically more secure than sending one cookie (assuming they are from the same domain/path as you mention).

My question was one of reducing bandwidth and resource usage.

Ok then I misunderstood what you're proposing. By the way, you can set the default cookie values using this but I agree that it should be httpOnly per default.