W3C home > Mailing lists > Public > w3c-dist-auth@w3.org > October to December 2006

Cross-site Request Forgery

From: Jack Bates <ms419@freezone.co.uk>
Date: Wed, 20 Dec 2006 13:41:36 -0800
To: w3c-dist-auth@w3.org
Message-Id: <1166650897.4143.40.camel@fis.lat>
I'm trying to protect my WebDAV project against cross-site request
forgery. http://en.wikipedia.org/wiki/Cross-site_request_forgery

What's cross-site request forgery?
--
Basically, it helps us to differentiate between user-initiated requests
and requests that have been made on behalf of the user, eg. if a user
visits another website and that website has <img
src="http://yourGallery.com/main.php?delete=everything"> then your
browser would make the request automatically and delete everything since
the request has been authorized. By adding a hidden form var and
checking for it on each request, we can identify such forged requests
since the hidden form var is not included. Of course, the auth token
needs to be a random value, hard to guess.

Obviously we can't tell the WebDAV client to include an auth token in
all requests, can we? Or should we add the auth token to the WebDAV URL?

Or is there any HTTP header sent by the WebDAV client by which we can
tell WebDAV clients and normal browsers apart?

This attack is slightly more difficult against WebDAV because sensitive
requests use special request methods (eg. "DELETE"). I tried using a
form to trick the user into making a sensitive request:

<html>
  <head>
    <title> Cross-site Request Forgery </title>
  </head>
  <body>
    <form action="/~jablko/gallery2-trunk/w/foo/bar" method="DELETE">
      <input type="submit"/>
    </form>
  </body>
</html>

However it did not work in Firefox. According to the W3C HTML spec, the
method attribute can only take values "GET" and "POST". Firefox
interprets any other value as "GET".

I also tried making a sensitive request with JavaScript and
XMLHttpRequest:

<html>
  <head>
    <title> Cross-site Request Forgery </title>
  </head>
  <body>
    <script>
      request = new XMLHttpRequest();
      request.open('DELETE', '/~jablko/gallery2-trunk/w/foo/bar');
      request.send(null);
    </script>
  </body>
</html>

This did work; it used my authentication credentials to delete the
resource.

Cross-site request forgery dangerous even if the user is prompted to
enter his/her password. With so many password prompts, I might enter
mine without thinking. It is more dangerous because browsers can
authenticate to WebDAV without user interaction.

Cookie/session based authentication:
 * Most WebDAV clients don't support cookies/session. WebDAV server
could perhaps ignore these credentials.

HTTP Basic/Digest authentication:
 * Because browsers cache username/passwords for subsequent requests, if
the user has already authenticated to the auth realm used by the WebDAV
server, the browser will re-use his/her username/password without
interaction.

HTTP Negotiate/SPNEGO authentication:
 * This single-sign-on mechanism is designed to reduce tedious password
prompts. If the user has a valid Kerberos ticket, the browser will
authenticate without user interaction.

I'm not sure how best to protect WebDAV against cross-site request
forgery. I appreciate any input! Thanks, Jack

Received on Friday, 22 December 2006 10:42:21 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 2 June 2009 18:44:15 GMT