Welcome!

AJAX & REA Authors: Marek Miesiac, Loraine Antrim, Liz McMillan, Yeshim Deniz, Chris Fleck

Related Topics: AJAX & REA

AJAX & REA: Article

Real-World AJAX Book Preview: A Safer More Secure AJAX

Real-World AJAX Book Preview: A Safer More Secure AJAX

This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs for the special pre-order price, click here for more information. Aimed at everyone from enterprise developers to self-taught scripters, Real-World AJAX: Secrets of the Masters is the perfect book for anyone who wants to start developing AJAX applications.

A Safer More Secure AJAX
As with any new technology or methodology, AJAX development has security risks. Many of these are easily avoided through good Web coding standards. Even so entire books could still be written on the elements of AJAX security. This chapter provides an overview of security issues to give the new practitioner a good idea of where to start.

Poorly designed AJAX applications can open holes for malicious scripts or data requests. Good server- and client-side validation is necessary to bulletproof AJAX applications.

The watchword is healthy handling. You want AJAX to exchange the information you want and need, but keep out the rest.

This section examines a few well-known examples of good and bad AJAX exploits.

The Best of Scripts, the Worst of Scripts
The beauty of AJAX is its use of the XMLHttpRequest. It lets us create compelling mashups, experiment, and open up the Web to all kinds of new possibilities. It also opens the door to unvalidated cross-site scripting (XSS) challenges that allow malicious users to inject powerful code into our applications. Theoretically, this code can do almost anything.

To combat this, modern browsers attempt to close off the possibility of XSS entirely. This makes sites more secure, but it greatly limits our abilities to do mashups. And mashups are becoming more common in mission-critical applications as more companies come out with databases or helper applications with open APIs.

There are a series of workarounds that enable safe multi-server scripting for the coder. However, it remains to be seen whether there will be tools to protect the user from scripts that use these workarounds to send data to undisclosed locations.

Don't You Know That You're My Hero?
The largest recorded AJAX security breach was in 2005 when a MySpace member known as "Samy" wanted to increase the size of his buddy list. The worm he created capitalized on the closed MySpace system and the network effect of friend-to-friend worm transmission to give him over a million friends in under 24 hours.

Exploiting some security holes in Internet Explorer and lax security and session validation on MySpace, Samy's worm attached itself to the bios of other users. When these infected pages were viewed, Samy would be added to the viewer's buddy list and he to theirs. When he was added to theirs, the code would be inserted on their pages and the worm would propagate.

MySpace stripped out JavaScript from incoming requests by looking for the word "javascript" in an attempt to thwart security breaches. But MySpace didn't account for "java" and "script." So Samy exploited a weakness in Microsoft Internet Explorer that recognizes "java" and "script" as "java script" and then embedded his request in the Cascading Style Sheet code that MySpace lets users add to their profiles.

Simple script validation can help avoid this kind of security breach - but it's important to be aware of browser quirks like the one Samy exploited. The code below shows how Samy exploited security holes in IE to become a friend to the unwilling:

main(){
var AN=getClientFID();
var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;
J=getXMLObj();
httpSend(BH,getHome,'GET');
xmlhttp2=getXMLObj();
httpSend2('/index.cfm?fuseaction=invite.addfriend_verify&friendID=11851658&Mytoken
='+L,processxForm,'GET')}

function processxForm(){
if(xmlhttp2.readyState!=4){return}
var AU=xmlhttp2.responseText;
var AQ=getHiddenParameter(AU,'hashcode');
var AR=getFromURL(AU,'Mytoken');
var AS=new Array();
AS['hashcode']=AQ;
AS['friendID']='11851658';
AS['submit']='Add to Friends';
httpSend2('/index.cfm?fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,'PO
ST',paramsToString(AS))
}

The MySpace Worm used a combination of Get and Post to achieve its goals. In this code snippet we see that the code uses GET to retrieve a token from a page and then uses Post to change the page.

This code relies on the absence of server-side validation of the transaction. Simple server-side session IDs would neatly solve this problem by ensuring that Posts that change pages are originating from a known session, rather than from an unrelenting "robot" like Samy's worm.

Cross Site Scripting, AJAX's Double-Edged Sword
The very nature of HTML and browsers enable users to easily view the underlying code of a given Web page. Protected values and fields can be quickly altered by users with even a little acumen. This leaves browser-side validation suspect - it's simply too easy to fake requests.

To reduce the likelihood of success by these fake requests, the server can generate session IDs that track the session itself. Data coming into the system without a current session ID would be rejected.

Cross Site Scripting (XSS) involves the interaction of a single Web page with multiple domains. In an XSS application, one Web page would make requests to more than one domain. This becomes dangerous when requests aren't appropriately validated or intended by the user. Malicious coders create requests or embed commands that are then sent to a server. Users can hijack other users' sessions and get personal information, they can alter accounts (as with Samy), or they can execute commands on the server.

For example, consider the case of Web-based blog authoring tools, which lets a logged-in user post to his blog. If, while the user is logged in to his blog tool, he browses to any other Web site, that Web site can embed code that attempts to post to known blog tool URLs. Here's a scenario outlining this:

AJAX is an ideal technique for this kind of XSS exploit because of the way it allows the browser to interact with the Web server without the complete page reloads that a user might notice.

Current browsers deal with cross site scripting security concerns by making XSS nearly impossible through what's called the "same origin" policy. This policy requires that all XMLHttpRequests be made to the domain of the current Web site. For example, if I'm viewing a page at http://www.domain.com:8080, I can only request information from an XMLHttpRequest from that protocol (http), domain (domain.com), and port (8080).

This is good in that it seals up a security hole, but it also blocks legitimate cross-site uses of AJAX. For example, many Web service APIs are available for data provision and data storage. These services are available on the different domains of their creators. Mashup Web applications can exist because this extra-server information is available. In many cases, it would be ideal for a mashup to use XMLHttpRequest to interact with services hosted on different domains.

But current browsers either completely restrict XSS or make it difficult to do directly. This makes mashup site design tricky. Simply inserting code and hoping your users have the right browser with the right settings won't work. Workarounds center on techniques to redirect requests and make the browser unaware that multiple domains are involved. In other words, the workarounds stick in the boundaries of the browser's same origin policy but use other means to bring together code and data from multiple domains. These include:

Application Proxies: Applications reside on the site's server and respond to XMLHttpRequests from users. The applications then directly make the Web Service call to one or more additional Web Service domains and send the data back to the users. This kind of proxy can be implemented in PHP or Java.

Apache Proxy: Apache Web server can be configured so that XMLHttpRequests can be invisibly rerouted from the server to target the Web Service domain. This is very similar to application proxies, but the proxy lives at the Web server level, rather than at the application level.

On-Demand JavaScript/Script Tag Hack: This workaround doesn't use XMLHttpRequest, but uses the HTML script tag to make a request to an application proxy. The proxy then returns the data wrapped in JavaScript.

Bookmarklet Intermediary: The bookmarklet intermediary injects JavaScript into an existing page loaded in the browser. The intermediary script then uses XmlHttpRequest to interact with the original Web page. The intermediary script can change the process data or the look-and-feel of the Web page. A good example of this is John Vey's Del.icio.us Direct.or. (http://johnvey.com/features/deliciousdirector/).

The intermediary isn't necessarily a way to get around XSS restrictions, but it can be used in conjunction with other techniques to provide extended functionality for existing sites that have AJAX APIs.

Both application and Apache proxies work by recognizing patterns in request URLs and then acting as Web clients to other servers. The following is a fictitious example.

A new Web mashup called my-town-songs.com combines data from two servers:

  • Every-song-evar.com is a Web Service that queries a giant database of song titles.
  • open-api-maps.com is a map service that provides map data for Web mashups.
This mashup takes the name of a place and returns a map of that place with little pins indicating the names of songs about that place . The client-side of the mashup application, an HTML Web page using AJAX, makes a request to my-town-songs.com that looks like this: http://my-townsongs.com/london. The server-side application acts as a proxy and uses the pattern /[place name] to proxy requests to every-song-evar.com and open-api-maps.com.

At this point, the my-town-songs.com application is acting as a Web client, not unlike a Web browser. It sends out two requests:

  1. http://every-song-evar.com?keywords=london
  2. http://open-api-maps.com?type=findMap&placeName=london
The Web browser doesn't "know" anything about these requests to multiple servers - from its pointof-view, it's only interacting with my-town-songs.com and functioning within the constraints of the browser's same-origin policy.

Our mashup gets results back from both servers. For example, every-song-evar.com returns a list of songs like:

A Foggy Day in London
London Bridge
London Calling
London Girls
London Traffic
Towers of London
Trams of Old London

Our mashup at my-town-songs.com can take the results from both servers, format them in JSON (JavaScript Object Notation), and return them to our Web browser.

The browser now has data that originally came from two different servers. But using my-townsongs.com as a proxy, the browser gets this data from only one server - the one from which the original AJAX request was initiated at my-town-songs.com.

Because the proxy gets around the same-origin policy, our AJAX code can now process the data and mash it up into its presentation to the user. Our code would be able to combine the song list with the map info as if they came from the same source. From the point-of-view of the browser, in fact, they come from a single source.

For more on AJAX and proxies, see Jason Levitt's article, "Fixing AJAX: XMLHttprequest Considered Harmful" at www.xml.com/pub/a/2005/11/09/ fixing-ajax-xmlhttprequest-considered-harmful.html.

This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs, click here to order.

About James Benson

Jim Benson, AICP, is the COO of Gray Hill Solutions in Seattle. Gray Hill creates tools for government and industry to harness and utilize real-time data. Jim has always driven applications for his clients to store and provide information in easily extensible ways. Web 2.0 has therefore been a natural environment for him. He is also involved with the Cooperation Commons and the Institute for the Future's Future Commons to study human cooperation and envision the future of cooperation. Jim's tags: Gray Hill Solutions (www.grayhillsolutions.com), Jim's Blog (http://ourfounder.typepad.com), Cooperation Commons (www.cooperationcommons.org), Institute for the Future (www.iftf.org).

About Jay Fienberg

Jay Fienberg is co-founder of Juxtaprose (www.juxtaprose.com) where he designs information architecture and user experience for Websites and information systems. He specializes in design for enterprise-scale, Web-based social and collaboration systems. Since the early 1990s, Jay has also designed and developed hypertext, database, and content management systems and worked in a wide range of programming languages including XML, SQL, SGML, Python, PHP, Javascript, Java, HTML, CSS, and APL. Jay has a number of blogs, websites, and online projects available via jayfienberg.com.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.