Shaun Inman wrote a nice piece on "Responsible Asynchronous Scripting" this week. One of the commenters on the blog mentions security as an issue with asynchonous scripting, but doesn't go into more detail. Here are my 2 cents on this (euro cents since I'm in Dublin at the moment).
Firstly, my own early experience with AJAX is a bit different from most. In 1998, I was implementing a Web application for a semiconductor company as a contractor, and I needed a way to convert a username to a numeric UserID in a Web form, without the hassle of reloading the form. I wrote a local scriptable Java applet which had no user interface, all it did was call back to a CGI script on the host Web Server. I used this mechanism to add interaction to the Web pages, without needing to re-load. I also used this same technique, with the same tiny applet, for another job where I designed a tax lookup Web application for the government here in Ireland. Later, I discovered that the little applet wasn't needed, since I could just use the XMLHTTPRequest object instead.
As we all know, the term "AJAX" was later applied to this type of asynchronous scripting, and it has become very popular. On my desk, the current copy of Application Developer Trends has a headline on the front that says "AJAX changes everything, believe it". So let's look at the security of this type of development.
In practice, "AJAX" usually means JavaScript code in the browser constructing a URL query by concatenating name=value pairs and then using the XMLHTTPRequest object to perform a HTTP GET against a server-side script, which in turn returns the response data back to the JavaScript code. This all happens without a page refresh. You can see it in action in sites like Gmail.
AJAX is closely related to REST-style Web Services. In REST, as in AJAX., the Web Service is usually invoked using a HTTP GET which sends up a query-string to the Web Server, and XML is returned back. I say "usually" because there is a big difference between what I'd call the "academic" REST model of using HTTP's GET, POST, PUT and DELETE verbs to interact with Web resources, and the "practical" REST model of always using HTTP GETs to interact with Web resources and never using POST, PUT, or DELETE at all. I gave a presentation about REST security, versus SOAP security, at the RSA Conference in San Jose earlier this year and I tried to emphasize that there is a huge discrepency between how REST is described in the literature and how REST is used in practice. In theory, the usage of GET in a REST Web Service should have "no side effects" on the Web Server side, whereas POST, PUT, and DELETE do. In practice, however, the vast majority of "REST style" Web Services use HTTP GET exclusively. I know from Vordel's customer base of Web Services early adopters that when I hear someone say "We are using REST for our Web Services", they almost always mean "we invoke our Web Services using HTTP GETs and pass the parameters in the URL Query-String".
Here is how I expressed this in the RSA slideset:
Now let's look at some specific security questions about AJAX:
"eval" with care REST Web Services return XML data to the client. However, although the "X" in AJAX stands for XML, there is a growing trend to send serialized JavaScript objects over the wire using JSON, rather than sending XML documents. On the browser, JSON allows these JavaScript objects to be instantiated using the "eval" command. This rings security alarm bells. This is one of the reasons why there are specific "JSON Parsers" which include some safeguards in their implementation of the "eval' command.
What's on the wire I can see why JSON is compelling from a developer productivity point of view, but I feel that a lot is lost if XML is not sent along the wire. It means that you cannot perform content-level analysis and routing on the XML traffic, not the mention the fact that you cannot use intermediaries to sign and encrypt the XML data. Obviously I may seem to be biased here since I work for a vendor, Vordel, which provides XML routing and security products that can act on AJAX data. But, even still, I think that if you're not using XML as the wire format, you are losing out on a lot of interoperability and extensibility.
"Call Home Only" works both ways. When I first came across XMLHTTPRequest, I assumed that it must use the same sandbox mechanisms as Java applets, so that it could only connect to the host Web server and not to third-party sites. And, sure enough, that's how its security model works. This is good. However, think about the other side of the connection. If you have written a script on the server which is invoked by the XMLHTTPRequest object on the browser side, how are you guarding access to this script? Is it vulnerable to an "AJAX Harvesting" attack? Are you limiting access to the Web Service at all? This brings us on to the next point.
What can AJAX learn from the "Developer Tokens" model used to limit access to REST-style Web Services In my RSA Conference presentation on REST security , I looked at how Amazon and Google manage access to their REST style Web Services. Both started with the idea of "developer tokens" which are issued to developers, and used to limit access to a certain amount of Web Services accesses per day. One amusing side-effect of this was when developers would post code up to their blogs and include their own developer ID in the code, resulting in their daily allocation being used up by their blog readers. Amazon's access control model for their REST Web Services is the more sophisticated, since it includes the usage of a local "secret access key" that is used to authenticate requests. In putting this model together, Amazon have reinvented certain aspects of WS-Security. I'd prefer to see this take the form of a WS-I profile, open to peer review, rather than being simply Amazon's proprietary model. Unfortunately this model doesn't apply well to AJAX since the "secret access key" could not be stored in the browser. OpenID looks like a much more applicable model for authenticating to Web Services, since it is (as the name suggests) open and not proprietary, since it works across sites, and since it doesn't involve confidential data being sent down to the browser.
AJAX snooping The connection from the XMLHTTPRequest to the Web Server usually takes place over an unencrypted link, meaning that the data can be snooped. For this reason, many AJAX developers choose not to send sensitive information over this connection. For example, in the Application Development Trends article, I read an interview with a developer from Alliance Reservations Network who says "We make it a point to never pass sensitive data across an AJAX request"].
Declarative audit trail With AJAX, the URL Query-String contains the parameters which are being passed from the browser to the Web Service. With SOAP style Web Services, the URL isn't so useful, since the data is in the SOAP body. It also means that you can filter AJAX messages using the URL and HTTP header only, whereas with SOAP messages you need products that understand SOAP [vendor hat on again here: like Vordel's XML Gateway]. Furthermore, the AJAX requests can be bookmarked, and they can easily be replayed. Recently, Dave Winer showed how a "tinyURL" short URL can be used in place of long REST-style URLs. This has clear uses for counteracting the fact that email clients have trouble with long URLs. But if it was to get widespread use, it would mean that you lose the ability to keep a declarative audit trail of AJAX and REST access that can be searched based on query parameters. It would also mean that you'd lost the ability to filter the traffic based on the name/value pairs in the QueryString.
------
Comments are welcome on all of this!
4:02:37 PM
|
|