tags:

views:

464

answers:

4

This is a question about generating CSRF tokens.

Usually I'd like to generate a token based off of a unique piece of data associated with the user's session, and hashed and salted with a secret key.

My question is in regards to generating tokens when there is NO unique user data to use. No sessions are available, cookies are not an option, IP address and things of that nature are not reliable.

Is there any reason why I cannot include the string to hash as part of the request as well? Example pseudocode to generate the token and embed it:

var $stringToHash = random()
var $csrfToken = hash($stringToHash + $mySecretKey)
<a href="http://foo.com?csrfToken={$csrfToken}&amp;key={$stringToHash}"&gt;click me</a>

Example server-side validation of the CSRF token

var $stringToHash = request.get('key')
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken')

The string being used in the hash would be different on each request. As long as it was included in each request, the CSRF token validation could proceed. Since it is new on each request and only embedded in the page, outside access to the token would not be available. Security of the token then falls to the $mySecretKey being known only to me.

Is this a naive approach? Am I missing some reason why this cannot work?

Thanks

A: 

CSRF token meant to prevent (unintentional) data modifications, which are usually applied with POST requests.

Thus, you must include CSRF token for each request that changes data (either GET or POST request).

My question is in regards to generating tokens when there is NO unique user data to use. No sessions are available, cookies are not an option, IP address and things of that nature are not reliable.

Then simply create a unique user id for each visitor. Include that id in a cookie or in the URLs (if cookies are disabled).

Edit:

Consider the following event:

You have logged-in to your facebook account and then entered to some arbitrary website.

In that website there's a form that you submit, which tells your browser to send a POST request to your facebook account.

That POST request may change your password or add a comment etc, because that the facebook application recognized you as a registered & logged-in user. (unless there's another blocking mechanism, like CAPTCHA )

Dor
Adding part of the token to a URL, and having the other half in the form means no protection at all.
blowdart
Sorry but what do you mean? I didn't wrote that...
Dor
Sure you did, "Include that id in a cookie or in the URLs (if cookies are disabled)." - you say to put the id in the URL, this simply isn't secure.
blowdart
I can't find any better idea how to store a session id when cookies are disabled.
Dor
Ah you meant put the session ID in the URL, and then keep half of the CSRF token in the session? When you were talking about the unique user ID I thought you mean the unique value used to generate the token. Apologies.
blowdart
A: 

CSRF utilizes the user's session, so, if you don't have one, there is no CSRF.

rFactor
+4  A: 

Is there any reason why I cannot include the string to hash as part of the request as well?

CSRF tokens have two parts. The token embedded in the form, and a corresponding token somewhere else, be it in a cookie, stored in a session or elsewhere. This use of elsewhere stops a page being self contained.

If you include the string to hash in the request, then the request is self contained, so copying the form is all an attacker needs to do, as they have both parts of the token, and thus there is no protection.

Even putting it in the form URL means that it's self contained, the attacker simply copies the form and the submission URL.

blowdart
You need to remember the token being stored on the server...
Jaco Pretorius
No you don't. One half could be kept in session, or it could be dropped via a cookie. It doesn't have to be stored on the server at all, usually it's cookie based so you don't have to rely on enabling sessions.
blowdart
A: 

You simply just need the same "token" in the URL/form and in the cookie. This means that you could have your page setting the token cookie to whatever it wants to (preferably some random value) by JavaScript and then just pass the very same value in all requests that goes to your server (as a URI ?param or form-field). No need to have your server generating the cookie.

This is safe as long as we trust that the browser doesn't allow pages from a domain to edit/read cookies for other domains, and this is assumed to be quite secure today.

Having your server generating the token will assume that this token can be safely transmitted to your browser without being picked up by any CSRF attempts (why take the risk?). Though you could put more logic into a server generated token, but to prevent CSRF there is no need.

(If I'm wrong here please let me know)

MyGGaN

related questions