So, I've been doing a lot of AJAX development recently and decided to have a little think about the security the various methods and techniques that I've been employing...
The basic AJAX situation...
You have a button on your page. On clicking the button, an XMLHTTPRequest is made to a URL to perform an action. The action is executed and the web page receives some sort of response to say whether the action was successful... It may also supply some data to display on the web page - perhaps a JSON object, or maybe a chunk of HTML.
The thing I was particularly interested in was the security around the URLs that the AJAX request hit... Essentially, these URLs are simply open points to execute actions against your application.
In my apps, you have to be logged in to perform any action that changes data in any way, so a user would have to be authenticated in order for these exposed URLs to be abused.
As I write this, I have multiple tabs open in my browser (IE at the moment incidentally). One of the tabs is logged into my webmail account. I still have [MySuperMarket].com open where I'm in the middle of putting together my weekly food shop. I have iGoogle open in another, my blog is open and logged in, the current tab I am looking at, and finally a couple of wikipedia articles in some more tabs.
This means I am currently authenticated against no less than 4 web apps, without taking into account any sites I have persistent log in enabled on (that check box that asks if you want to stay signed in on this computer)... God knows how many of them I have.
So, I have established that at least 4 sites currently trust any requests sent from my browser.
My thinking followed the idea that any request from my browser - regardless which tab, would be able to execute actions against any of these logged in applications. Time to try and execute some actions in one of these apps from outside of it's domain then...
A Proof of concept...
I went to the tab with the supermarket site open. Opened fiddler, and hit a button to add some cooked chicken to my shopping cart:
The highlighted row above shows a call has been made to the url:
along with a bunch of querystring parameters (detailing the ID of the particular product, the quantity, and various other things).
I then removed the chicken from my cart.
Crafting the web page to abuse this action
I figured, all I would need is a webpage that creates an XMLHTTPRequest to the above url, with appropriate querystring data supplied. I created the following HTML file:
Hopefully you can see it is a basic page with a hyperlink. I have used jQuery to attach a click event to the hyperlink which fires an AJAX request to the relevant URL.
I opened the HTML page in my browser, clicked the link, went to the supermarket tab and refreshed my cart... Hey presto - There's some chicken in there.
It appears all I have to do is get people to follow a link to the HTML page I have created, and, if they are logged into the particular supermarket, everyone will be getting extra chicken with their shopping orders
Ha ha ha. Today unwanted chicken chaos, tomorrow the world.
This is obviously a bit of a silly little example, but is good for a POC. Potentially I could be performing all sorts of undesirable action.
Furthermore, what does this mean for online banking sites, betting sites or other places where money can be moved around?
At first consideration, this appears to be a fairly serious problem. It's known as a cross site request forgery or XSRF.
Whilst it doesn't just effect AJAX apps, I think that as people start to embrace AJAX it will be easy to make mistakes, unless we think carefully about exactly what functionality we are providing to the world at large - intentionally or not.
Further musings on this coming later...