What is a CSRF token? What is its importance and how does it work?
I am writing an application (Django, it so happens) and I just want an idea of what actually a "CSRF token" is and how it protects the data.
Is the post data not safe if you do not use CSRF tokens?
Cross-Site Request Forgery (CSRF) in simple words
- Assume you are currently logged into your online banking at
www.mybank.com
- Assume a money transfer from
mybank.com
will result in a request of (conceptually) the formhttp://www.mybank.com/transfer?to=<SomeAccountnumber>;amount=<SomeAmount>
. (Your account number is not needed, because it is implied by your login.) - You visit
www.cute-cat-pictures.org
, not knowing that it is a malicious site. - If the owner of that site knows the form of the above request (easy!) and correctly guesses you are logged into
mybank.com
(requires some luck!), they could include on their page a request likehttp://www.mybank.com/transfer?to=123456;amount=10000
(where123456
is the number of their Cayman Islands account and10000
is an amount that you previously thought you were glad to possess). -
You retrieved that
www.cute-cat-pictures.org
page, so your browser will make that request. - Your bank cannot recognize this origin of the request: Your web browser will send the request along with your
www.mybank.com
cookie and it will look perfectly legitimate. There goes your money!
This is the world without CSRF tokens.
Now for the better one with CSRF tokens:
- The transfer request is extended with a third argument:
http://www.mybank.com/transfer?to=123456;amount=10000;token=31415926535897932384626433832795028841971
. - That token is a huge, impossible-to-guess random number that
mybank.com
will include on their own web page when they serve it to you. It is different each time they serve any page to anybody. - The attacker is not able to guess the token, is not able to convince your web browser to surrender it (if the browser works correctly...), and so the attacker will not be able to create a valid request, because requests with the wrong token (or no token) will be refused by
www.mybank.com
.
Result: You keep your 10000
monetary units. I suggest you donate some of that to Wikipedia.
(Your mileage may vary.)
EDIT from comment worth reading by SOFe:
It would be worthy to note that script from
www.cute-cat-pictures.org
normally does not have access to your anti-CSRF token fromwww.mybank.com
because of HTTP access control. This note is important for some people who unreasonably send a headerAccess-Control-Allow-Origin: *
for every website response without knowing what it is for, just because they can't use the API from another website.
Yes, the post data is safe. But the origin of that data is not. This way somebody can trick user with JS into logging in to your site, while browsing attacker's web page.
In order to prevent that, django will send a random key both in cookie, and form data. Then, when users POSTs, it will check if two keys are identical. In case where user is tricked, 3rd party website cannot get your site's cookies, thus causing auth error.