CSRF: alternative solutions

As I understand from various discussions here and from articles
around, I've learned that CSRF is a security leak which involves:

1) user visites http://www.mybank.com/login
2) the server sends a cookie, call it MyBankSID, with the login information
3) user visites http://www.dangerous.com/ within the expiration time of cookie
4) the user clickes a link (or sends a form) to
http://www.mybank.com/pay?to=hacker
5) the browser sends MyBankSID cookie, which grants access to user's
bank account
6) money goes from the user to the attacker

To stop CSRF, we need to stop this algorithm at one of these steps.
We can stop it at 1), removing state information (like cookies or
Authorization headers) for sensitive resources. This is the secret
token approach: the session id is embedded in every link and inside
every form sent to the web application and continuously changes

We can stop it at 2), which involves that the user never visites
dangerous web sites. This is our unfortunate situation: sensitive web
apps hope that the user never visites web sites which exploit CSRF

We can stop it at 3), preventing or asking permission for cross site
requests which use non-safe methods (PUT, DELETE and most important
POST). This could also mean making always visible what the destination
of a link is, before the link is traversed.

We can stop it at 4), preventing the user agent from sending
automatically state information when the request is originated from a
foreign (and possibily untrusted) origin. This means that cookies are
not sent for requests that are not same-origin.

We can stop it at 5), preventing the website from considering the
state information authoritative and thus processing the request
associated. This requires an out-of-band indicator for user's
intentions, which is currently the Origin header (assuming that the
user is conditioned by originating page's content)

All of these solution have pros and cons:
Solution #1 requires that the server keeps track of the secret id.
This can be very difficult to implement for web apps authors and
requires a lot of preprocessing on the server side, even for static
pages (for example the login page or the contact page).

Stopping at 2) is not really a solution, it is just putting the head
under the sand.

Solution #5 is possible, but requires a new header that proxies or
firewalls may strip and current UAs don't send. In addition, it is
possible that it will have the same flaws as Referer (which is very
similar to Origin), like browser not sending it from https origins.
Also, I'm not sure how it would interact with manual entering of URIs,
like emails or IMs which say: "paste this into your browser address
bar"

Then we have solution #4. This may hurt web apps that currently
require sensitive cross-site requests, but I'm not sure that there are
any, and they could work with automatic redirection to a login page.
Architechturally, assuming that the UAs keeps authentication info and
automatically sends it is a bad idea that we should not encourage, and
so designing web services that require this.

Lastly, solution #5 doesn't require any change in the security model
or in deployed web apps. The annonyance to the user could be avoided
with something like "remember this choice". Yet, the user interface
must make very clear where the traversal started, where it will end,
and what information the UAs will send authomatically.
This is the solution I prefer

I hope that this will start a positive discussion, that could maybe
improve existing and proposed CSRF prevention techniques.

Giovanni

Received on Monday, 8 June 2009 13:53:29 UTC