22

I was just going through the OWASP's Cheat Sheet for CSRF Prevention. Regarding the double submit cookies method, it says:

the site should generate a (cryptographically strong) pseudorandom value

This method completely relies on the fact that Cookie/Header can not be injected by the attacker.

An attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy.

Then, why should the pseudo random value be cryptographically strong?

3 Answers 3

19

Short answer: To prevent brute forcing the CSRF token.

Let's take a trivial example: let's say your token is a single digit, accepting values from 0 to 9.
Now sure, an attacker cannot read this value from the cookie or header, but she does not have to - she can just have the attack send 10 CSRF requests, one with each possible value. One of them will be correct.

Using a cryptographically strong random value will prevent this, and can prevent the attacker from trying to scale up this attack (by having the attack send e.g. 1000 requests instead of 10, or 10,000, or... )

13
  • Can't we just counter this, by increasing the number of bits? Dec 18, 2013 at 13:06
  • 5
    @thefourtheye: At issue is predictability. A cryptographically strong random value cannot be predicted (which is why it is cryptographically strong). Sure, you can generate a 64-bit number, but if the attacker can predict the numbers you generate (or can narrow down the possible numbers to a brute-forceable range) then the extra bits add no extra security. Dec 18, 2013 at 13:18
  • @MartijnPieters Yup. I agree that. But, increasing the number of bits will make the token difficult to predict, right? Dec 18, 2013 at 13:20
  • 4
    @thefourtheye: 1 << 63 + randrange(10) is 64 bits, but just as easy to predict as the example in this answer. So no, it depends on how the bits are generated. If you do it properly, you have a cryptographically strong random number anyway. Dec 18, 2013 at 13:22
  • 2
    @thefourtheye: Yes, see Is a rand from /dev/urandom secure for a login key? Dec 18, 2013 at 13:25
3

Combining the best of both answers:

  1. The token length needs to be proportional to the number of victims and the number of requests per victim. If an attacker convinces X victims to navigate to his page (by way of spam or phishing attacks) and each such page attempts Y different tokens then you need to protect yourself against 2x*y attacks. For example, if your token length is 16 bits long, an attacker needs to send out 216 emails that attempt 1 token each, or 28 emails that attempt 28 tokens each. An attacker can test multiple tokens with a single click using Javascript or by embedding multiple malicious image links per page.

  2. You want to use a cryptographically-secure random number generator to prevent attackers from requesting multiple tokens themselves, then using the sequence they got to predict what tokens other users will get in the near future.

2

It doesn't

It just has to be pseudo random.

CSRF is not compatible with brute force attacks. Consider the attack vector:

  1. Malicious user crafts a special email or web page with HTML that posts to the site of interest
  2. User is logged on to the site of interest, and the session ID is passed passively (it's a cookie)
  3. User is tricked into clicking the link in the specially crafted email or web page
  4. Link "forges" the request. The link doesn't have to contain the session ID because it's in the cookie. And it doesn't have to pass the CSRF token found in the header (it's passed passively-- it's a cookie). But it does have to contain the CSRF token in the form post.

There is no way a hacker is going to trick anyone into clicking a link hundreds of times. Even if it's a script that sends a ton of requests on a single click (assuming the hacker has figure out how to do that-- browsers don't allow cross-domain AJAX requests, so we're probably talking about a page containing hundreds of clear GIFS or something else totally whacky), it's not going to be able to get through a whole lot of search space without timing out.

Also, there is no way for the attacker to determine if the attack worked for a particular value-- it's a "fire and forget" attack.

So the idea that the CSRF token can be brute forced is far fetched at best. The hacker would have to be personally logged on-- which is a different attack entirely.

The only reason you need any entropy at all really is because CSRF attacks tend to be delivered via spam. Let's say you're an idiot and your CSRF token only has 16 bits of entropy, and the hacker sent out 65,536 spam emails with the exact same token. 65536/2^16 = one of those attacks would actually succeed. Assuming 0% of the emails hit spam filters, 100% of the users opened them, and 100% of the users happened to be logged into your app at the moment they clicked the evil link.

Other than hoping to sucker in a ton of users, there's no way for a hacker to scale the attack large enough to call it a brute force attack with any significance to it.

11
  • 5
    Actually, this is wrong, on several key points. Brute force IS possible, just not at the level to crack 32 (or even 16) bytes of entropy. And while browsers do not allow cross domain AJAX requests, they DO allow cross domain POST requests - aka submitting a form (which is easy to do silently in javascript). Alternatively, that "page containing hundreds of clear GIFS" (or rather 1x1 pixel, at the very bottom of the page far below the break) is not so "wacky", and in fact HAS been seen in the wild. So yeah, if the CSRF token space is small enough, or predictable enough, it CAN be brute forced.
    – AviD
    Dec 19, 2013 at 8:31
  • 2
    That is why CRNG is required, to ensure that it is not predictable, as I explained in my answer. Remember, the CSRF attacker does NOT need to "trick" you into clicking a link, the CSRF requests can be sent out silently - either via POST requests in javascript or "hidden" IMG tags.
    – AviD
    Dec 19, 2013 at 8:34
  • Yes it is "easy enough" to submit a form silently in Javascript-- but only one (see here). Maybe two if you work really hard (see here). It is impossible to submit 2^16 forms. More importantly, the hacker has absolutely no control over timing-- the user will open the page at his leisure. Arguing about 64 bits of entropy and/or "true" unpredictability is absurd when you understand the attack vector.
    – John Wu
    Dec 19, 2013 at 15:13
  • 2
    Huh what? It is trivial to submit multiple standard POST requests via javascript. I don't understand the confusion in those links, and the SO question is not exactly the same thing you're referring to here. I agree that 2^16 bits of entropy would be too difficult to brute force in this way, but 10 / 100 / 2^8 is easily within realm of feasible. I am not sure what part of the attack vector you're misunderstanding.
    – AviD
    Dec 19, 2013 at 15:25
  • 2
    And I explicitly agreed, that with enough entropy it is resistant to brute force, and you don't even need 256 bits of entropy to get there. What we don't agree on, is that CSRF tokens with low entropy can be brute forced, and that CSRF attacks do not require "tricking" the victim.
    – AviD
    Dec 19, 2013 at 15:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .