6

According to Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet , the recommended solution to protect web site from CSRF attacking is to implement Synchronizer Token Pattern. And This requires the token to be random or unique.

And recently, we are trying to apply this to our web site. And one of my colleges wants to generate the token by encrypting the current sign-in user's id concatenating a timestamps with a safely kept password. And then append the token into the form.

When user sign in, we set a logged-in user id cookie under our site domain and the root path /. So if we can find this special cookie, then we get the logged-in user's id.

When we get the token, we try to decrypt it to get an user id and an timestamps. We then compare the user id with the current sign-in user's id and use the timestamps to check if the token timeouts.

So I want to know if this works and what's the pros and cons?

The reason why we try to do this is that we try to avoid sessions. Some frameworks like Struts2 have build-in implementations based on sessions.

George
  • 6,297
  • 3
  • 14
  • 10
  • 14
    If you can append the password, does that mean you guys are actually storing the password clear text in such a way that the application can directly access the passwords? Because I think you might have another problem than CSRF ... – Lucas Kauffman Jan 11 '13 at 09:38
  • @LucasKauffman Yes, the application can directly access the password used to encrypt the data. Even worse, we use only one password for all tokens. Besides the password problem, how about the CSRF problem? – George Jan 11 '13 at 09:46
  • How do you identify users? i.e. what do you have in the cookie instead of the session id? And what kind of crypto do you apply to it? – CodesInChaos Jan 11 '13 at 11:18
  • 2
    I think you're missing some context here. As you comment below, that you are not using sessions (why not? What is the architecture? Does this affect the CSRF issue?) - how are users identified and authenticated? Is CSRF even an issue at all? This would be based either on a sessionId cookie, or HTTP Authentication Headers. Otherwise, CSRF is probably not an issue at all. Either way, this could greatly affect the efficacy of any solution provided. Please edit your question to add all relevant context. – AviD Jan 11 '13 at 11:51
  • If you're not using a MAC on the tokens, your system is probably broken independently from CSRF. – CodesInChaos Jan 11 '13 at 11:52
  • Just curious about what platform you're using. Many popular platforms already have well-defined mechanisms for dealing with CSRF, and building your own may simply be a waste of time. – David Stratton Jan 11 '13 at 14:30
  • 2
    wayyy over kill when all you need is a random number – rook Jan 11 '13 at 17:01
  • @AviD, We set cookie like logged-user-id=122929292 for example when user sign in. Then we check this on the server side to get the logged-in user's id. – George Jan 12 '13 at 12:32
  • @George correct me if I'm wrong, but that sounds a lot like a server side session...? And, if you are building your own session management, that's usually a pretty bad idea - most frameworks will have it built in, and if you build your own it will probably be broken. – AviD Jan 12 '13 at 20:59
  • @AviD, it's just a cookie the server set and not a session cookie, we keep it for a week by default. So the requests sent by this user will carry this cookie. Does it sound like a server side session? – George Jan 16 '13 at 10:19
  • What does this cookie contain? Some form of non-permanent identifier, that can be correlated back to his primary identity, with perhaps some additional temporal information. Correct? If so, then yes, this does sound very much like a server side session, even if its not the standard built-in mechanism. – AviD Jan 16 '13 at 21:55

3 Answers3

13

This is probably a bad mechanism, since it violates Kerckhoff's principle. If an attacker knows how your "encryption" works, he can just encrypt his own CSRF blob for a specific user and use it in targeted attacks.

CSRF leverages the fact that your browser will send a cookie containing a session ID that authenticates you to the server, even if the request is generated by an automated script. In order to protect yourself against this, you just need to require a token that is unknown to an attacker, and that is not automatically sent by the browser without direct instruction. The standard way to do this is to generate a random value, known as a CSRF token, and add it to the parameters of a POST request. As long as the target script verifies the CSRF token somehow, you're protected.

The simplest way to do this is to generate a random CSRF token when the session starts, and store it as a session variable. It can then be injected into forms that require CSRF protection, and checked by the target script.

Adding any "extras" to this scheme, like encryption / timestamps is snakeoil - i.e. it provides no real security and complicates the scheme, which results in a potentially greater attack surface. Remember: don't be a Dave!

Polynomial
  • 133,763
  • 43
  • 302
  • 380
  • We wasn't allowed to use session at all. Because if we store the token in session, we must maintain a distributed session due to multiple application servers. So we try to avoid sessions. – George Jan 11 '13 at 10:06
  • 2
    So how does your server know that a user is "logged in"? – Polynomial Jan 11 '13 at 10:40
  • When user signed in, we set a logged-in user id cookie under our site domain and the root path /. So if we can find this special cookie, then we get the logged-in user's id. – George Jan 12 '13 at 12:28
  • 1
    @George So if the user changes the cookie value to a different ID, he could just log in as someone else... :s – Polynomial Jan 12 '13 at 13:14
  • Use signed session cookies, include the CSRF token in the signed session cookies, and problem solved? – yfeldblum Jan 13 '13 at 18:07
  • @yfeldblum, this may be the so called Double Submitted Cookie solution. It works for us. But we want to simply it. – George Jan 16 '13 at 10:09
  • @Polynomial, the cookie is protected by Httponly attribute. So the client browsers cannot modify it, right? – George Jan 16 '13 at 10:29
  • 5
    @George Of course they can. Httponly just stops the cookies being accessed by JavaScript - any cookie editing addon for a browser will let the user change the cookie. – Polynomial Jan 17 '13 at 20:52
4

one of my colleges wants to generate the token by encrypting the current sign-in user's id concatenating a timestamps with a safely kept password. And then append the token into the form.

That's fine and a commonly-used approach where sessions are not available. But use a standard MAC for this (eg HMAC-SHA256) instead of your own single-layer concatenated-hash.

Another consideration is key lifecycle management: are you planning to change the server secret every so often? Do you have a mechanism to provide for a smooth changeover when you do (or when you are retiring the secret after a compromise)? Or is it OK to break everyone's old tokens in that scenario?

It sounds like you are using a similar signed-value scheme for the auth cookie. In that case you should consider (if you're not already) including a user password identifier as part of the cleartext/signed material, so that when the user changes their password it invalidates all previously-issued tokens. This could be a generation number, change-timestamp or storage salt.

There is also the implication that, because the datum you are matching for XSRF protection is the user ID, you are unable to protect the login form itself. Consider what would happen if an attacker used XSRF to cause a user to log in automatically to an account of the attacker's choice, maybe without the user noticing what account they're logged in as; does that potentially constitute a threat?

An approach that solves this if you need it is to add auth cookies for non-authenticated users, and include a secret in the auth cookie. Then include/sign that secret in the XSRF token: effectively the XSRF token is signing the auth cookie.

bobince
  • 12,534
  • 1
  • 27
  • 42
2

This is a valid approach in protecting against CSRF attacks. Some advantages over traditional methods include:

  • It’s not session-dependent
  • It doesn’t expose sub-domain vulnerabilities as per Double Submit

It’s called the Encrypted Token Pattern. Check this link for a full explanation and architectural overview. Also see the official OWASP description.

Paul Mooney
  • 151
  • 3
  • What about storing the CSRF token in local storage instead of the hidden field? im mostly asking because i would love to have a solution that works across page reloads. – Faris Zacina Sep 15 '15 at 18:36
  • Yes, there is no explicit requirement to store the Token in HTML mark-up. Storing the Token is session storage is perfectly acceptable. The point of the Encrypted Token Pattern is to offer flexibility, in terms of token-storage, on an application by application basis. – Paul Mooney Sep 17 '15 at 08:52