I wrote a post about CSRF tool and readers noticed an intentional mistake in it — storing a token in a plain cookie can be exploited with cookie forcing (like cookie tossing we saw on github, but works everywhere). TL;DR With MITM attackers can replace or expire any cookie (write-only)
Actually I don't think it's mistake in CSRF protection design, I still think problem is about horrible cookies design. But we got to deal with current situation, and taking into account this feature I came up to concise and effective protection.
At first glance it might look ugly. But web is ugly so it's OK.
Step 1. We simply put csrf_token value into session. Wait, we do not store it in database, because it's pointless. We do not store it in signed cookie either like Rails do (this is also overwork).
I propose to literally store csrf_token in session cookie:
sid=123qweMySeSsIon--321csRFtoKeN
You only need a middleware on top of the stack slicing the token after --.
Step 2. Attacker still can fixate the whole session cookie value (sid + csrf token). So always refresh csrf_token after login to make sure csrf_token wasn't fixated.
Can you see anything simpler than this trick? I guess everything using two separate cookies will require signatures and cryptography with server secret. Too much work for a design mistake W3C made.
Although CSRF protection on its own is not popular, cookie forcing protection is way less popular — don't be surprised how many websites/frameworks are vulnerable. How to check: it is vulnerable if you can replace csrf_token cookie (use Edit This Cookie) not breaking session or csrf_token remains same after login.
For example Django framework (csrftoken cookie is not integrated with session), twitter (doesn't refresh authenticity_token after log in, so it can be fixated), etc.
Google Reader is dead, make sure to follow me on another website.
Google+ is much better than Twitter. Here is your page: https://plus.google.com/110421481014101227624/posts - for those who thinks the same :)
ReplyDeletetrue
DeleteIf it's not too stupid question, please, explain what the difference between storing token in separate cookie and in session cookie? (if we always refreshing token)
ReplyDeletebecause when you store it separately attacker can use Cookie Forcing and change csrf token not changing session cookie, simply saying inject a new value.
DeleteIf these values are tied (same cookie) he cant do so
why can't he do that? i still don't get it....because you also say:
Delete"Attacker still can fixate the whole session cookie value (sid + csrf token). So always refresh csrf_token after login to make sure csrf_token wasn't fixated."
so all i understand from this is that besides refreshing the session id you also have to refresh the CSRF cookie after login......
yes, id must also be refreshed, you are right
Deleteit's still not clear. why can't attacker do cookie forcing if csrf + session are in the same cookie?
Deletebecause he cannot change token only, he also must know session value to change cookie
DeleteSorry for disturbing you again. Can you please read on this page http://docs.angularjs.org/api/ng.$http part about XSRF and give your opinion, is it safe enough or not.
ReplyDeletei think it's weird
Delete>We recommend that the token is a digest of your site's authentication cookie with a salt for added security.
if salt means session secret then stealing the secret we can guess someone's token.
but it looks close to integrity because of signing
So client-side should then parse cookie name to receive token and send in http-header received token with POST request?
ReplyDeleteBecause otherwise I don't see how can I validate token on server side.
Deleteno, csrf token should not be parsed from the cookie, it should be ALSO stored in , say, meta tag in the header
DeleteIt's much less convenient way, when HTML are static pages, supposed to be filled by results of XHR-requests (AngularJS it's exact example of this variant).
DeleteAlso, it's just unusable variant for REST APIs.
CSRF can be obtained with /token.json for example. It must be stored in httponly cookie
Deleteafter more than a year, has your opinion changed about this method?
DeleteIf I put the csrf token in meta, then the browser can not cache it. Ugh! so ugly. but the web is ugly, so it's OK!
Hi, thanks for sharing your ideas :)
ReplyDeleteA stupid question,
have you ever heard of Synchronizer Token Pattern?
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
In my opinion your approach here is quite similar from some points of view, do you think that Synchronizer Token Pattern is not good enough?
Maybe you wrote about that in another post, if it is so please let me know.
csrf is synchronizer pattern. cookie forcing is another attack and i updated CSRF design to make it secure by default from all attacks. Nothing changed generally, it's cosmetic trick
DeleteThank you for your reply.
DeleteI clearly misunderstood the point here :)
Just to clarify - we assume that despite using HTTPS, a MITM attack has write-only access to the target's cookies - IE they can read them and not write them?
ReplyDeleteSo the idea being, that they can simply replace an individual cookie for CSRF Token, but if it's part of the session ID, they cannot, because they'd have to reconstruct it from the session ID which requires write access?
Thanks
exactly, to replace SID+TOKEN cookie you will must to know SID too, because values are tied into a single cookie
Delete