justinas / nosurf

CSRF protection middleware for Go.

Home Page:http://godoc.org/github.com/justinas/nosurf

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cookie tokens not masked?

paulbellamy opened this issue · comments

It seems like the tokens sent out in cookies are never masked. They are masked before being stored in the context, but then the unmasked token is sent out in the cookie. That seems incorrect to me, but I'm not a crypto expert.

This is based trying to use this library, and based on reading: https://github.com/justinas/nosurf/blob/master/handler.go#L182

Also, it seems like this https://github.com/justinas/nosurf/blob/master/handler_test.go#L243 is doing the token masking on the client side. Is that what I should be doing in javascript before an ajax call?

Tokens are masked when used in the HTML form (acquired by calling Token(r)). You should use the same value for AJAX.

I assumed only masking the form values was enough, but it would be nice to check if it's susceptible to BREACH that way.

Ok. Maybe I'm just misunderstanding how the X-CSRF-Token header is meant to be used. I had assumed you were meant to take the value of the cookie, and use that as the header value in your response, but I think that you are saying that you should actually pass the result of Token(r) to your javascript app somehow (rendering into a form/page, etc), and use that as the X-CSRF-Token header value. And that your JS app should not touch the cookie or use it's value for anything. Additionally, you should use a different value of Token(r) for each form, so as to not re-use a one-time-pad. Is all that correct?

Thanks for your help. I'm just trying to make sure I get this right.

Yes, the intended way is to take Token(r). The cookie might as well be HttpOnly. Reusing the single value from Token(r) should be fine, as BREACH requires many requests to recover secrets and the pad is randomized for every request.

@justinas where is the pad randomized for every request? I couldn't find it

Update: found it. ctxSetToken called on every valid-looking request while invalid requests get an error and empty requests get a new token with pad. This does not interfere with fetching the sent token which is not placed in the context.