Attempt to perform Cross Site Request POST Forgery on JBoss/JAX-RS application

Having read about Cross Site Request Forgery I tried to find out how easy it is.

Consider an application that uses cookies for session tracking. Most if not all do nowadays. If you are logged in to the application then any request made to that web site will have the session cookie attached. This does not matter if the request came from the browser window/tab you believe is logged in or any other browser window.

Consider an application that use HTTP GET requests to perform actions. For example if our payroll application were to accept the following request:

GET http://our.company.com/staff/richard/salary?newValue=10000000

I may be tempted to try to trick my manager into making that request. OK, maybe a million pounds would be a bit unsubtle. One technique I could use would be to send an email with the following image tag

<img style="width: 0; height: 0;"
     src="http://our.company.com/staff/richard/salary?newValue=10000000">

In this case my mischief would be easily traced. Perhaps I could embed the image on a blog or other page that my manager visits.

POST Requests

Any sensible application should not perform actions as a side effect of a GET request. This is part of the HTTP convention: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”. This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

Apart from some caveats, data returned from a GET request is protected by the browser cross domain protections. The holes in this, such as the ability to intercept Javascript arrays in JSON data, are being closed by the browsers and can be easily worked around in the application design. So in order to change my salary I must be able to forge a POST or a PUT request.

I was surprised how easy this was to accomplish. An invisible IFrame contained a FORM with a method of PUT and an encoding of text/plain. It was possible to construct a form which would result in a valid JSON request. The request will have an = sign somewhere in its content, but that can be placed somewhere harmless in the JSON data. In my test I included it in a description field. It was possible to submit the form using Javascript without any interaction or warning in the browser.

Fortunately the attack against our application failed. We overrode the JAX-RS providers, so our result may not be the same as yours. We perform strict content type negotiation, so the request content type of “text/plain” was refused. It seemed a near miss. Our setup was made to give us control of date formats, not because we were thinking about security.

Unfortunately our content type negotiation does not save us. Sockwave Flash reportedly allows cross domain requests to be made with arbitrary content type. We implemented CSRF tokens in our requests to protect against cross site request forgery.

The Future of Cross Domain Requests

Cross Domain Requests are a potentially very useful feature. They make it easy to make mashups in the browser, without needing server side code to perform the requests on behalf of the user. An application may wish to expose an API to cross domain requests. Care would be needed to ensure that they are secure.

New features in Javascript make Cross Domain Requests easy. They can be performed using XmlHttpRequest as normal. I have tested this in Chrome using the Sencha Ext-JS library and noted that Chrome sent an OPTIONS request to my server. It seemed a little more paranoid than the standard required in http://www.w3.org/TR/cors/, sending a pre-flight request for a GET request. The standard seems designed to fail gracefully. Servers that do not know about this feature will not respond with the correct headers and access will be refused.

This entry was posted in java, javascript. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.