tags:

views:

102

answers:

6

I'm wondering if the following method will completely prevent CSRF, and be compatible with all users.

Here it is:

In the form just include an extra parameter that is: encrypted(user's userID + request time). Server-side just decrypt and make sure it's the right userID and the request time was reasonably recent.

Aside from someone sniffing the user's traffic or breaking the encryption, is this completely secure? Are there any downsides?

A: 

It's not completely secure, as it may be possible for an attacking site to guess the User ID.
If you use a per-session encryption key, it is secure. (But then all you need to do is send the raw key, and it's already secure)

Also, remember about timezones and inaccurate clocks.

SLaks
Timezones shouldn't be an issue if it's the server checking a time that the server issued.
amdfan
@amdfan: I assume that he means the current time on the client; otherwise, it would be almost pointless.
SLaks
amdfan is right, I mean the timezone of the server, and I don't think the attacking site could guess what the encrypted value of a userID would be. They wouldn't have my encryption key. If they had my encryption key that would be a whole different issue.
Kyle
They might not necessarily need your encryption key if the ciphertext is in a format that allows for patterns to be discovered and exploited.
Russ Cam
@Russ My assumption is that the encryption would be secure. If it wasn't secure then they are attacking the encryption, not this method of preventing CSRF
Kyle
@Spines - the point is that the canary should not be predictable. A constant UserID combined with a varying DateTime could be considered highly predictable, encrypted or not. I'm no security/cryptography expert, but in order for a canary to be *more* secure, you ideally require an element of pseudo-randomness with high entropy included in the value to be encrypted. For example, the CSRF anti forgery token in .NET uses the RNGCryptoServiceProvider to generate a pseudo-random value to include in the canary, in addition to the UserID, DateTime and an optional salt.
Russ Cam
A: 

It should work, yes. Though I would suggest you use a random number for UserID when you create new users, rather than a simple incrementing number (obviously, make sure it's unique when you create the user). That way, it's hard for an attacker to "guess".

Dean Harding
the attacker can't guess anything since its encrypted and he doesn't have the encryption key right?
Kyle
+5  A: 

While your approach is safe it is not standard. The standard way to prevent CSRF attacks is to generate pseudo-random number that you include in a hidden field and also in a cookie and then on the server side you verify that both values match. Take a look at this post.

Darin Dimitrov
In addition, you could include the canary in session as opposed to a cookie, although putting it in a cookie alleviates the need to store it on the server
Russ Cam
+1, Good link, at the end of the article he says "An even stronger, albeit more complex, prevention method is to leverage server state...", why does that make it more secure? Is storing the random value in the cookie and in the form not completely secure?
Kyle
@Darin Upon review, I have concluded that I strongly disagree with you. Please read my answer.
Rook
+3  A: 

One major downside is that your page will 'timeout' if the user leaves their browser open longer than the time frame you decide is reasonable before they post the form. I prefer sites not to rush their user into committing their action unless the action is inherently time-sensitive.

Venr
right, thats why "reasonably recent" could mean anything, i was considering having "reasonably recent" to mean like 5 days.
Kyle
+1 Though it is a valid concern
Kyle
A: 

Having the UserID and a DateTime is a start, but you also want a pseudo random number value preferably with high entropy in addition in the canary token. Basically, you need to reduce the predictability of the token in a page in a given context. Having only the UserID and a DateTime could in theory be possible to break after some time as it is not "random enough". Having said that, CSRF attacks are generally scripted and not directly monitored, so depending upon the exposure of your application, it may be enough.

Also, be sure to use a more secure encryption algorithm such as Rijndael/AES with a key of bits sufficient for the security of your application and a pseudo random initialization vector.

Russ Cam
wouldn't the encryption of the 2 values make it so the attacker couldn't guess?
Kyle
That depends on the encyption algorithm and the encryption mode. For example, AES with ECB mode operation is not considered "secure" as the same plaintext with the same key will produce the same ciphertext.
Russ Cam
right, I would obviously use an encryption algorithm that is secure.
Kyle
Be sure to use a known secure algorithm and adhere to best practices in using it.
Russ Cam
A: 

The security system you have proposed is vulnerable to attack.

Block ciphers like AES are commonly used as very secure random number generators. They are called CSPRNGs. However, like any random number generator you have to worry about what you are seeding the algorithm with. In this case you are using user's userID + request time both of which the attacker can know, your implementation doesn't have a Key or IV so I assume they are NULL. The attacker is building the request so he will always know the request time. The userId is likely a primary key, if you have 100 users then the attacker could forge 100 requests and one of them will work. But the attacker might just want to force the administrator to change his password, admin's usually have a primary key of 1.

Do not re-invent the wheal, very good random number generators have already been built and there are also anti-csrf libraries.

Rook
@The Rook, he is not using `user's userID + request time`. In his question the OP stated that he uses `encrypted(user's userID + request time)`. Of course he didn't specify what does `encrypted` mean but if he uses AES it would be extremely difficult for an attacker to forge the token even if he knows the user id and the request time as he doesn't know the secret used to encrypt and decrypt for this purpose.
Darin Dimitrov
@Darin so you agree that his proposed system is vulnerable to attack without additional sources of entropy.
Rook