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).
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,
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:
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 :
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.