13

The below quote is from http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html

When a user visits a site, the site should generate a (cryptographically strong) pseudorandom value and set it as a cookie on the user's machine. The site should require every form submission to include this pseudorandom value as a form value and also as a cookie value. When a POST request is sent to the site, the request should only be considered valid if the form value and the cookie value are the same. When an attacker submits a form on behalf of a user, he can only modify the values of the form. An attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy. This means that while an attacker can send any value he wants with the form, he will be unable to modify or read the value stored in the cookie. Since the cookie value and the form value must be the same, the attacker will be unable to successfully submit a form unless he is able to guess the pseudorandom value.

The above method prevents CSRF attacks by comparing the psuedorandom value in the cookie and form. However why does the value need to be returned with the form also ? I am assuming both the form and cookie have the same encrypted value that they are returning to the server. And the server validates it by decrypting the value.

So even if the value is only returned only by the cookie, then the server can decrypt it and verify the request. What purpose does the return of the encrypted value with the form serve?

murtaza52
  • 45,047
  • 27
  • 78
  • 118

2 Answers2

52

Ok, so let's break up the problem to atomic questions for better understanding:

What is this CSRF ?

It's a type of web application vulnerability. At the most basic level, the reason for a CSRF is that browser's do not understand how to distinguish if an action was performed deliberately by a user (like say by clicking a button on a form, or clicking a hyperlink etc.) or if the user unknowingly performed the action (like say user visited a page from some domain, say bad.com, and bad.com sent a request to good.com/some_action while the user was already logged into good.com).

So what is the impact of CSRF

Now let's replace good.com above with facebook.com. And let's assume that when a user, logged into facebook.com, posts a comment on his wall, there is an HTTP GET request that gets sent, of the form say,
https: //facebook.com/postComment?userId=Abhinav_123&comment=HiIAmAbhinav.

Now let's assume that the user, while he is still logged in to facebook.com, visits a page on bad.com. Now bad.com belongs to an attacker where he has coded the following on bad.com:

<img src="https: //facebook.com/postComment?userId=Abhinav_123&comment=I_AM_AN_IDIOT>

Now as soon as the user's browser loads the contents of this page on bad.com, a request also gets sent to facebook.com as :

https: //facebook.com/postComment?userId=Abhinav_123&comment=I_AM_AN_IDIOT

because the browser tries to render the img tag. To do so it needs to fetch the resource specified in src and hence it sends the above HTTP GET request. So essentially the attacker could actually submit a request to facebook.com on behalf of the user without him actually knowing this.

Now what could have potentially prevented this attack ?

If only there was some way to identify if the request was made by the user intentionally. So to do this, anti-CSRF token came into the picture. It is just a random, unique string generated by the server (facebook.com in our example above) and sent over to the user and set in the browser of the user as a cookie. Now for every request involving some sensitive action (like posting a comment in our facebook example above) the browser will send this random string also along with the request and the server before performing the action would verify if the random string is the one that it had sent to the browser or not.

The idea is that this random string will not be known to the attacker. So even if the attacker creates a img src as shown above, and the user visits bad.com, the action (of posting a comment in our example above) will not be performed, because for the action to be performed, apart from the URL, an additional thing is also required, which is the random string, which the attacker does not have.

But setting this random string in a cookie again has a HUGE flaw

Because of the way cookies are designed and the way in which browsers handle cookies, setting this random string (the anti-CSRF token) in the cookie will not serve our purpose. By design, cookies are automatically sent to the server with every request that the client makes to that server (simply put, and details ommited for simplicity. For more details refer : RFC2965)

So, in our example above, the attacker does not really need to know the random string. The posting comment action will still be completed because as soon as the user visits bad.com and loads the post comment URL (as explained above) the random anti-CSRF token (present in the cookie) will automatically accompany the request.

So what is the solution then ?

Instead of putting the anti-CSRF token in the cookie, the server (facebook.com) needs to put it as a hidden parameter in a form and make when the user requests for posting a comment this form (holding the anti-CSRF token) should also be posted.

Now the attacker has no way of performing this sensitive action on behalf of the user (unless he somehow finds out the random anti-CSRF token itself)

Now coming to the problem of login CSRF and double submit cookie

A lot of times websites would protect themselves against CSRF attacks by deploying some form of anti_CSRF token architecture. But a lot of times websites do not care much about protecting their login form against CSRF attacks. Why ? - Because even a login form is vulnerable to CSRF and an attacker tries exploiting it by framing a login request to good.com (facebook.com) through his domain (bad.com), the the user would still need to enter his valid credentials to get loggedinto facebook.com. These credentials are available only with the genuine user and not the attacker and hence the attacker can not frame a successful login request.

So what is the attack opportunity for the attacker here ?

The attacker can create his own account with facebook.com. He now has a valid set of credentials for himself. Now he frames the login request to facebook.com, with his login credentials, and on his domain (bad.com). Now when the user visits the page, bad.com, the user is logged into my account. I as an attacked can later see all the activities performed by the user on the account possibly disclosing sensitive info as well (like say friend requests sent if the user chooses to send new friend requests, messages sent to someone, again if the user does so after logging into my account. All of these possibilities depend on how convinced the user is that he has logged into this own account, which again the attacker can take care of by making his own facebook page look as close to the victim's as possible to con him into believing that it is his account)

So now what is the mitigation technique against this?

It is a double submit cookie that we need now here.

What exactly does this mean

Double submitting cookies is defined as sending a random value in both a cookie and as a request parameter, with the server verifying if the cookie value and request value are equal.

How does it help mitigate the attack ?

As per the implementation principle of a double cookie, when an anonymous user (not logged in user) visits a login page the server sets a cookie with some random string in the user's browser and also sets the same in a request parameter as well (say a form hidden field). When user submits the login request, these things get submitted with the request - the user credentials, the random string in the hidden form field and the cookie holding the random string (that gets sent automatically of course).

Now an attacker will have access to his own credentials, the random string set by the server in cookie and in the hidden form field for the attacker. When the attacker sends this crafted login request to the user (the victim), and the user tries to make this request, the user is still not logged in and is an anonymous user for the server so far. So the server will set a cookie on the user's browser with a different (from the attacker's) random value. Now when the user makes the request for login through the attacker's crafted link, the request will contain the attacker's credentials, the attacker's random string in the hidden form field, but the user's random string in the cookie (coming from the user's browser). Now when this request reaches the server, the random strings in the cookie and the hidden form field would not match and thus would be flagged as an exception and handled accordingly.

So this the reason for the the return of the encrypted value with the form as well. Hope it clears the concept.

qre0ct
  • 4,420
  • 6
  • 37
  • 73
  • Hi! I am trying to understand why this approach is needed now if we have CORS. If it is needed please explain why! Thanks for advance – Yuriy Feb 12 '18 at 10:01
  • Hello @Yuri, if why is anti CSRF mechanisms still needed despite CORS, is what you're trying to ask, let me take a shot at it and try explaining. As far as simple requests in CORS are concerned (without pre-flight) CSRF is still possible. The not so simple requests (with pre-flight) it really depends on the way the CORS policies are configured. Because, the pre-flight (OPTIONS) request can still be made by an adversary by exploiting a CSRF bug, and then it would depend on what the server responds back in the response. If the server is too permissive, the attack would still go through. – qre0ct Feb 12 '18 at 12:04
  • 1) "As far as simple requests in CORS are concerned (without pre-flight) CSRF is still possible" - Do you mean simple requests described here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS ? If yes, pre-flight requests are needed only for old servers or for servers under development with old code(it is explained there https://stackoverflow.com/questions/15381105/cors-what-is-the-motivation-behind-introducing-preflight-requests). 2) "If the server is too permissive" Is it really very hard properly set up cors settings on server? – Yuriy Feb 12 '18 at 12:17
9

Cookies are sent automatically with every request, regardless of whether the request was initiated by the original site or by a third party site. That’s why a cookie alone does not suffice as every request will contain it.

But by having the token also in the request itself, an attacking site cannot generate valid requests any more as they can’t get hold on the user’s token.

Gumbo
  • 594,236
  • 102
  • 740
  • 814