LWN.net Logo

Cross-site request forgery

By Jake Edge
October 17, 2007

Cross-site request forgery (CSRF or XSRF) is yet another web application flaw that can have serious impacts. By exploiting the trust that the targeted site has in a logged-in user, usually encapsulated in a cookie, CSRF can perform actions on behalf of that user, without any indication that the action took place. It shares many traits with its better-known sibling, cross-site scripting (XSS), but, unlike a site targeted via XSS (for login spoofing or cookie stealing for example), the target web site can make changes to avoid CSRF.

A CSRF attack targets a specific web site, one that requires credentials to perform actions. Financial and shopping sites are common targets, but as described in last week's article on this page, home routers and similar equipment are also targets. Another popular target is sites like Digg, where users vote on particular stories to increase their popularity; an attacker can drive more traffic to a site of their choosing by using a CSRF exploit to add votes.

The exploit itself is typically contained in an <img> tag or form submission, with Javascript sometimes used to hide the form submission. The URL used causes some kind of side effect on the target website as long as a properly authenticated cookie is delivered with the request. For example, if LWN had a voting system, a tag like the following could perform a CSRF exploit:

    <img src="http://lwn.net/vote?type=y;story=some_lame_story_URL" width=0 height=0>
When the browser goes to fetch that "image", it helpfully sends along any cookies that correspond to the domain; if the vote application wasn't written correctly, anyone viewing the web page - and who was also logged-in to LWN - would add a vote for the story. There would be no indication that anything had happened, other than possibly a fleeting notice in the browser noting a connection to LWN.

Getting the user to visit the page with the CSRF is done in the usual way, via a link in email, instant message, or on another web page. CSRF does not require inserting code into the vulnerable website, which is the hallmark of XSS; instead it exploits the target from afar. The link the victim follows will not in any way indicate the target site.

There are a few things that web application programmers can do to eliminate CSRF problems; the basic idea is not to perform actions solely based on a proper cookie. Just as some non-internet authentications require two forms of identification, web applications should do the same. The second identification should come from something other than the cookie, something that can be known only by a properly authenticated user.

Two basic techniques are used, random form tokens or re-authentication. For sensitive operations, the best protection is to require the user to provide their credentials (username and password for example) before performing the action. This can be cumbersome, so, for less sensitive actions, hidden fields with random names and values can be inserted into each form, associated with a particular session, and checked on form submission. This isn't completely secure, as the values might be guessed, but with sufficient randomness, it is good enough for many operations.

It should be noted that preventing CSRF requires that all XSS problems are removed first. An XSS flaw can be used to retrieve the form, then grab the random tokens before submitting the CSRF request. XSS may also be able to spoof the user into entering their credentials, which would allow the CSRF to bypass re-authentication as well.

CSRF has been called the "sleeping giant" of web application security flaws, because it has yet to be exploited widely. It is only a matter of time, web programmers should be making the changes needed to ensure that their sites are not vulnerable.


(Log in to post comments)

Cross-site request forgery

Posted Oct 18, 2007 1:10 UTC (Thu) by jwb (guest, #15467) [Link]

The real problem underlying XSRF is that the self-styled "developers" behind most web hacks don't respect the difference between the GET and POST request methods. A GET should not have side effects! If I can vote in a poll on your site using nothing other than a GET, that is an HTTP protocol violation. Quoting from RFC 2616 (which is almost 10 years old):
Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property...

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI...

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

Cross-site request forgery

Posted Oct 18, 2007 2:56 UTC (Thu) by elanthis (guest, #6227) [Link]

Even if the app only modifies data in response to a POST, it is still very trivial for a site
to include a hidden form with automatic submission thanks to JavaScript.

The hidden magic numbers in form submissions is one approach to solving this I never thought
of.

I've just relied on the HTTP referer header: sans a bug in the user's browser, sites and
scripts cannot forge this header.  Someone could trivially write their own utility or program
which performs HTTP requests with a forged referer (curl and wget both support setting this to
arbitrary values), but then they wouldn't have the proper authentication cookie.

Not the most robust solution nor all that ideal in theory, but it's Good Enough(tm) in
practice.

Cross-site request forgery

Posted Oct 18, 2007 3:01 UTC (Thu) by jwb (guest, #15467) [Link]

I agree that you need further measures to protect against malicious webmasters, but they are a
small part of the problem.  The larger part of the problem is that anybody can put <img
src="whatever"> into a forum post (including this one) which causes a simple GET request.  If
your application has side effects on GET requests, then it is vulnerable to this very simple
attack.

Cross-site request forgery

Posted Oct 18, 2007 3:04 UTC (Thu) by jwb (guest, #15467) [Link]

It should be noted that certain forum software is rather more permissive about the sorts of things which can be posted by anonymous users, while other software can be very restrictive.

Cross-site request forgery

Posted Oct 18, 2007 3:19 UTC (Thu) by tetromino (subscriber, #33846) [Link]

You forgot to add a <marquee>.

Cross-site request forgery

Posted Oct 18, 2007 5:27 UTC (Thu) by mitchskin (subscriber, #32405) [Link]

lol, the medium is indeed the message.

Cross-site request forgery

Posted Oct 18, 2007 7:32 UTC (Thu) by Los__D (subscriber, #15263) [Link]

MY EYES, MY EYES!!! :D

Cross-site request forgery

Posted Oct 25, 2007 18:07 UTC (Thu) by devinjones (guest, #11272) [Link]

Thank goodness for firebug.

Cross-site request forgery

Posted Oct 18, 2007 10:44 UTC (Thu) by epa (subscriber, #39769) [Link]

A hidden form that automatically sends POST requests to some other site without user
intervention?  Do you have an example?  I'm just surprised that this is allowed by
Javascript's security model (as tightened up by recent browsers).

Of course I agree strongly with the grandparent; don't use GET requests for stateful
operations.  That is just asking for trouble.  I once worked in a web development shop where
the policy was that clickable links were somehow cooler than form submit buttons, so the user
management page had a 'delete' link for each user.  A customer was using a web accelerator
program that prefetches links (a perfectly allowable thing to do, provided it just GETs) and
deleted all users from the site.

Hidden POST forms

Posted Oct 19, 2007 0:53 UTC (Fri) by jamesh (guest, #1159) [Link]

It is trivial to create such a page. An outline of such an attack is:

  1. Include an iframe on your page, possibly hidden. Something like "<iframe name="foo" style="display: none"></iframe>
  2. Add a form element on the page with target="foo" as an attribute. This will cause the post to be loaded into the hidden iframe.
  3. Set the action attribute of the form to the site you want to attack, and the method to "post".
  4. Include all the form data you want as hidden form fields.
  5. Add an onload handler to the page that calls the submit() method on the form.

It worked pretty well in the browsers I tried, and doesn't give the user any indication that the form post occurred. So it isn't enough to just put all your unsafe operations into POST requests.

"Referer" header checking and nonces as hidden form fields will stop this attack dead in its tracks though, so they are worth investigating.

Cross-site request forgery

Posted Oct 26, 2007 15:12 UTC (Fri) by anton (guest, #25547) [Link]

[...] it is still very trivial for a site to include a hidden form with automatic submission thanks to JavaScript.
Not a problem for me, because I have disabled Javascript. Maybe just like some web designers show their lack of competence with messages like "Turn on JavaScript", other webmasters could show their security competence by welcoming users that have JavaScript enabled with "Turn off Javascript".

Cross-site request forgery

Posted Oct 19, 2007 9:34 UTC (Fri) by ekj (guest, #1524) [Link]

Sure they can have side-effect, the quote you include says as much.

What it says is that "the side-effects of N > 0 identical requests is the same as for a single
request."

In other words, for a GET-request it should make no difference if you visit the link 1 time,
or 200 times, the side-effects should be identical. There is allowed to be a difference
between visiting the link 1+ times, and visiting 0 times.

That's NOT the same as saying there should be no side-effects.

An example: Voting for a story on Digg. If you vote yes for a certain story once, or 100
times, the result is the same: your vote is registered as a yes.

Another example: Adding a certain book to your amazon wishlist. Whether you do the relevant
GET-request once or 10 times, the side-effect is the same: that book will appear on your
wishlist. (once, not 10 times!)

So no, respecting the difference between GET and POST will do precisely nothing at all to
combat this particular vulnerability, though it would have -other- advantages.

Cross-site request forgery

Posted Oct 18, 2007 10:56 UTC (Thu) by rwmj (subscriber, #5474) [Link]

Not sure about "sleeping giant". CSRF is routinely used to exploit home ADSL routers, with requests of the form http://192.168.2.1/firewall.cgi?disable. With a trivial extra image you can also pick up the exploited user's public IP address.

Rich.

Cross-site request forgery

Posted Oct 18, 2007 11:32 UTC (Thu) by skx (subscriber, #14652) [Link]

I wrote about this previously here:

http://www.debian-administration.org/articles/465

Whilst the main diagnosis of GET/POST abuse is correct it is still possible to submit forms
via POST with a little user action.  Consider a form which is hidden and a link which has
'onClick=form.submit()' for example.

Cross-site request forgery

Posted Oct 31, 2007 9:18 UTC (Wed) by wingo (subscriber, #26929) [Link]

Thank you for this article, I had not seen it so clearly explained.

Copyright © 2007, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds