9

I generate a random anti-CSRF token per session and store it in a cookie (with the http_only flag set). Then I add that token to forms (in a hidden input field) and links.

When receiving a request on the server, I check that the cookie and the anti-CSRF token field of the form or link exist and that the two values are the same; if not, it is considered a CSRF attack and the request is rejected with a proper message.

Is this mechanism safe/sufficient as a minimum? (That is to say, in the absence of security holes in the browser.)

I think that an attacker can't read or set the cookie of a domain that he doesn't own, so he can't forge a request that has the same token.

Gilles 'SO- stop being evil'
  • 50,912
  • 13
  • 120
  • 179
H M
  • 2,897
  • 6
  • 22
  • 21

4 Answers4

5

You say "session" - do you have a server-side session? If so, why not put the CSRF token in the session instead of a client-side cookie? That's the normal pattern; it prevents an attacker being able to use their own generated CSRF token value against another user in the case where they have cookie fixation.

Another similarly watertight approach not needing an extra cookie, if you don't have server-side storage, is to create a value including the user or session ID and sign it using a MAC (typically HMAC) with a server-side secret. The server can then verify that the token in the form came from the user whose session it is.

attacker can't read or set the cookie of a domain that he doesn't own

Well, probably... usually. Ways that cookie injection tends to happen (other than XSS in which case you already lost much worse):

  • browser bugs, outdated "generic domain" tables/rules etc
  • vulnerable neighbour domains (eg set cookie on www.example.com from test.example.com)
  • allowing your site to be served from an attacker domain (always check the Hostname: is a recognised-good domain name)

These are typically marginal issues but they depend on factors potentially outside your control as an application author. So for security-sensitive systems it's generally a good idea not to rely on your cookies being unfixatable.

bobince
  • 12,494
  • 1
  • 26
  • 42
  • i prefer not to use php sessions for storing the token; i am not using sessions for authentication. to make my anti-csrf system more secure i can use the hash of the user's authentication cookie/key as the anti-csrf token. is this scheme good enough now? – H M Mar 19 '13 at 15:16
4

Purely as an Anti-CSRF mechanism that sounds reasonable to me. The standard protection is to use a random token in a hidden form field and then check it on submission, so it looks to me that the only difference in your scheme is that instead of holding that token server-side you're comparing it to a token in a cookie. The solution you've come up with sounds rather like the "Double Submit cookies" option from the OWASP Anti-CSRF Cheatsheet

Obviously if there are other issues in your application (e.g. Cross-Site Scripting) you're likely to have problems but then XSS causes all sorts of problems.

Rory McCune
  • 60,923
  • 14
  • 136
  • 217
  • in OWASP Anti-CSRF Cheatsheet they say: "Alternative generation algorithms include the use of 256-bit BASE64 encoded hashes." this obviously seems overkill! 128 bit should be more than enough on the web. afaik 128 bit entropy randomness still can't be defeated even in offline attacks. – H M Mar 18 '13 at 15:34
  • 1
    Why isn't this pattern considered the [Syncrhonizer Token Pattern](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern) ? I ask because I am doing the same thing: After authentication, create a CSRF token, and encrypt it in the user's cookie as a MAC. Each form has a csrf token equal to the cookie's csrf token. The csrf token from the form is compared to the user's cookie's csrf token. – Matthew Moisen Feb 25 '16 at 21:00
1

According to my views this is not completely safe implementation, since its only validating that the value of cookie and the post param are "same and exists", what if there is a CRLF Injection Vulnerability aka HTTP Response Splitting in the application which lets me set another cookie named "csrftoken=test" and the csrf post param value to "test" and send the request - this bypasses the csrf check as a whole since the both values are test and matches.

Correct me if i am wrong.

StackB00m
  • 170
  • 2
  • 8
  • It's true that you can use CRLF Injection to insert your own header in the response from targetsite.com, this defeats double-submit-cookie. However, if you can use CRLF Injection to insert headers in a response from targetsite.com, then it seems like you could also insert two CRLFs and then just serve arbitrary page content from targetsite.com, which would be equivalent to a xss attack which could manipulate all content on targetsite.com anyway. (No, I didn't spend the last 6 years thinking about your question, I just saw it.) – Bennett Jan 30 '20 at 23:53
0

An attacker can send you a link your browser will open when you have a session in your protected application. This can happen even by showing images in an email. In this case the request from your browser contains the session cookie but not the anti-CRSF token and the server can invalidate the malicius request from the victim's browser. CSRF tokend have to live in the server session and in the html page, not in the cookie that is sent avery time from the client. It is also advisable to regenerate the value at every request (one time token) and asking the login credentials again for special requests (change password, apply email filter ecc).

DavidC
  • 51
  • 3
  • 3
    They don't _have_ to live in the server session. [Double Submit Cookies](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Double_Submit_Cookies) is one such method that doesn't require server side state. Also, [you don't need to regenerate the value on every request](http://security.stackexchange.com/a/56520/8340). – SilverlightFox Aug 06 '14 at 15:59