[WEB SECURITY] Suggestions for the CSRF FAQ

Brian Eaton eaton.lists at gmail.com
Sun Jan 28 11:42:42 EST 2007


The CSRF FAQ at http://www.cgisecurity.com/articles/csrf-faq.shtml is
a great document, and sorely needed.  I've got some suggestions for
two of the questions in the FAQ.

> What can I do to protect myself as a user?

The FAQ's current answer is that user's are helpless.  Is that really
true?  If you restrict the web sites you visit you can reduce your
exposure.  If you limit the amount of time you are logged into web
sites you can reduce your exposure.  For example, if you are concerned
about CSRF attacks on your bank account, limit the amount of time you
are logged in to your bank's web site.  Log in only when you need to
perform a task, and close the browser as soon as you are done with the
site.  Also, don't visit other web sites or view untrusted documents
while you are logged in to your bank's site.

> What can I do to protect my own applications?

I think the FAQ's answer to this question is basically correct, but a
little more detail about the trade-offs involved in the different
solutions might be helpful.  I've written up a few notes (OK, a lot of
notes) about how to go about adding CSRF protection to various types
of applications.  I'd appreciate some constructive criticism on these
approaches.  If there is consensus that these approaches are
technically sound and make sense in the real world, perhaps they
should be included in the FAQ.

*** Before you start adding CSRF protection ***

The first step in protecting your application against CSRF is to fix
any cross-site scripting vulnerabilities.  If your application is
vulnerable to XSS, CSRF protection is not possible.  Javascript
malware will defeat whatever protection you put in place.

The next step is to identify which functions of your application you
want to protect against CSRF.  Not all function needs to be protected.
 In fact, CSRF protection can make your web application less useful
because it prevents others from linking to portions of your site.
Which parts of your application require CSRF protection is ultimately
a business decision, but as a general guideline pages that cause
changes to data should be protected against CSRF.  Pages that display
data without changing it probably don't require CSRF protection.  For
example, a page that shows a stock quote probably doesn't require CSRF
protection (wouldn't you like other sites to be able to link directly
to that page?)  A page that triggers a stock purchase probably does
merit CSRF protection.

Once you've decided which functions require CSRF protection, there are
several mechanisms for providing that protection.  Broadly speaking,
CSRF protection mechanisms fall into two categories, those that reduce
target surface and those that prevent cross-site linking.

*** Reducing target surface ***

CSRF attacks rely on using a session that a user has already
established to trigger an action without the user's consent.  In
general, if a user is not logged in, that user cannot be affected by a
CSRF attack.  You can reduce the risk of a successful CSRF attack by
using short session activity timeouts in your application.  If a user
has been inactive for several minutes, log them out of the
application.  The choice of session time limits poses a trade-off
between usability and security and is ultimately a business decision
rather than a technical one.  If your users complain about being
prompted to log in frequently, you may need to increase the time
limits.

Requiring POST requests can also reduce target surface, by making it
harder for attackers to find an accomplice web site to use as a
launching pad for the CSRF attack
(http://www.webappsec.org/lists/websecurity/archive/2007-01/msg00158.html).
 Many popular web sites restrict the HTML content that users can
create, but do allow arbitrary img tags.  Such web sites can be used
as unwitting accomplices to a CSRF attack.  One of your users may view
a page on such a site that contains an attacker controlled img tag.
Their browser will then automatically send a GET request.  If your
application accepts such GET requests as legitimate, then an attacker
has a wide choice of potential accomplice web sites.

It is possible to automatically send a POST request from a browser,
but it requires a wider degree of control over the HTML page.  In
general a user will need to view an attacker controlled web page in
order to trigger an attack using a POST request.  This limits the
number of potential accomplice web sites an attacker can choose from.

*** Preventing cross-site linking ***

Reducing target surface is a good idea, but should not be your only
line of defense for CSRF protection.  Stronger CSRF protection
requires making it impossible for other web sites to trigger an action
on your web site.  This can be done either via the use of secret
tokens that are included and verified with form submissions, or by
requiring that a user confirm a request by submitting a password or
other authentication code as the final step in a transaction.  Neither
of these mechanisms is perfect from a security perspective.

The problem with asking users to reenter their password frequently is
that it makes for a poor user interface.  People may complain.  Aside
from the usability problems, frequent password prompts encourage
people to type in their password without thinking, and so may increase
your exposure to phishing attacks.  It also needs to be noted that an
XSS vulnerability in your site could allow javascript malware to sniff
the password as the user types it in.

However, secret tokens pose some security risks of their own.  An XSS
vulnerability in your web site means that attackers can read your
secret tokens, so you must fix your XSS vulnerabilities before
attempting to add CSRF protection to your web site.  Aside from XSS
bugs making your CSRF protection useless, the IE mthml vulnerability
(http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-2111) can also
let an attacker read your secret tokens.  The IE mhtml bug violates
the browser same-origin security model, and so it will probably be
fixed eventually.  (Also see
http://sla.ckers.org/forum/read.php?4,1975#msg-2036 for an interesting
discussion of how to prevent the mhtml bug from reading pages on your
web site.)

Poorly configured Flash crossdomain.xml files can also make CSRF
protection more difficult
(http://www.hardened-php.net/library/poking_new_holes_with_flash_crossdomain_policy_files.html).
 The flash crossdomain.xml file is a feature, not a bug, so you will
need to deal with this problem for the forseeable future.  You can
mitigate the risk of this feature being used against you by being
cautious in what you include in crossdomain.xml files.

Despite the problems with using secret tokens for CSRF protection,
this tactic is widely used.  The different mechanisms of generating
and verifying tokens merit discussion.  Which method is best for you
depends on your web development platform and the requirements of your
application.

If your platform supports sessions, then you can generate a
cryptographically strong random number and store it in both the
session and as a hidden form field.  When processing the form
submission, verify that the token submitted with the form matches the
token stored with the session.  The secret token should be changed
periodically and should be generated independently for each user.  How
often to change the secret token is a matter of some debate.  Changing
the token frequently mitigates the risk of an attacker guessing the
token or obtaining it through some other means.  However, if the token
changes too frequently then you risk breaking your web application for
those people that use the back button of their browser.  A user might
hit the back button a few times, then submit a form from a cached
page.  If the token has changed since the page was cached, your web
application will have to reject the form submission even though no
CSRF has occurred.

Note that if your development platform requires the presence of the
session ID in each request as a hidden form field, you are already
protected against CSRF.  The session ID acts as the secret token.

If your platform does not support sessions but you can use HTTP
cookies, you can use a similar solution.  Instead of storing the token
in the session, store it as a cookie on the user's browser.  When
processing the form submission, verify the token included in the form
matches the cookie.  This is less secure than storing the token in the
user's session, because other web applications in the same DNS domain
could still be used as launching platforms for CSRF attacks.  They
could generate their own secret token and force the user's browser to
include a matching token in a form submission.  (Signing the secret
token does not mitigate this risk.  The other server could first send
a request to your web application to receive a signed token, then
include that signed token in the CSRF attack.)  As with the previous
method of CSRF prevention, the token should be changed periodically.

If your platform does not support sessions and you prefer not to use
HTTP cookies, http://developer.yahoo.com/security/ offers a solution
under the heading "Protect Against Request Forgeries".  Include a
user-specific cryptographic signature with your forms and verify the
signature when processing the form submission.  The key element of
this solution is that an attacker must be unable to predict at least
one of the signed elements.

Cheers,
Brian

----------------------------------------------------------------------------
Join us on IRC: irc.freenode.net #webappsec

The Web Security Mailing List: 
http://www.webappsec.org/lists/websecurity/

The Web Security Mailing List Archives: 
http://www.webappsec.org/lists/websecurity/archive/
http://www.webappsec.org/rss/websecurity.rss [RSS Feed]



More information about the websecurity mailing list