Buy one XSS, get a CSRF for free

Cross Site Request Forging (see http://en.wikipedia.org/wiki/Cross-site_request_forgery for more information) has been around for a while now. It misuses the trust of a web application that every request sent by the browser is wanted by its user.
For example, if you know that i am logged in to our blog admin backend most of the time, and you know its url and software, you could trick me into visiting a special prepared url. That url contains a small javascript that automatically submits a fake form to our admin backend, and short time later everybody is surprised to read on our blog that Mayflower will leave the domain of web application development and open a butcher’s shop instead.

Since the authors of our blog software are smart people, they implemented a CSRF protection. And not only them, even we not as smart PHProjekt developers implemented one.
There are three popular ways to protect your software against CSRF:

  1. using POST instead of GET
    The non working but popular counter measure. It helps against requests hidden in image tags, but it won’t for requests forged by javascript.
  2. a hidden one time key / token in every form This is what we – and a lot of other people, too – did. Every form gets a token, and only if this token exists the form is accepted. The remote javascript can’t know the token, so it can’t submit a valid form
  3. referrer-check
    Another neat way to protect against CSRF, if there is no strange browser or proxy configuration that prevents the referrer header involved.
    If the origin of a submission is from a different domain, don’t trust it.

Whether you implemented a, b or c – if you got an XSS on your site, your protection does not help anymore. XSS allows you to inject javascript into the target hosts javascript sandbox. This allows you to submit XmlHttpRequest (XHR) calls to the target server.

  1. XHR, as well as javascript DOM injections, can be used to submit a post form
  2. The token can be circumvented by a XHR request that reads the original form page and extracts the token form variable
  3. XmlHttpRequest.setRequestHeader(‚Referer‘, ‚http://targetdomain.com/spoofedreferer.php‘) allows you to set a fake header.

Conclusion:
If you want to secure your application against CSRF, make sure that there are no XSS on your site, too.

Für neue Blogupdates anmelden:


5 Gedanken zu “Buy one XSS, get a CSRF for free

  1. > The remote javascript can’t know the token, so it can’t submit a valid form

    Note that you can reintroduce huge security problems by improperly using crossdomain.xml, see http://shiflett.org/archive/267 for details.

    > referrer-check

    That’s completely user-based, so I’m wary about implementing something like that. As you mention, you could end up accidently locking out users (esp those that may be covering their tracks by having configured their browsers never to send referer headers).

    > make sure that there are no XSS on your site, too.

    Easier said than done, especially for rich text input. For those of you looking for a good HTML filter, I’d recommend something I wrote: HTML Purifier (http://hp.jpsband.org/)

    • Hi Edward,
      For crossdomain.xml: Yep, you could use it to shoot yourself in the foot even without having an XSS on your own site :-)

      For your html-filter: i am pretty convinced that a whitelisting filter is the right way to go. Nevertheless i don’t believe in 100% security when html is involved.
      But for sure i’ll have a look at it.

      Best Regards,
      Johann

  2. yes referrer checks aren’t a good idea. people running norton internet security wind up blocking them by default it seems. i would never recommend using referrer checking, its bit me in the past.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.