Build AJAX Security With JSON

Conferences about new development environments, such as AJAX, typically feature sessions showing cool new things you can do with it. Inevitably, though, some sessions will focus on security issues. They'll be like a trip to the dentist: less fun, but absolutely necessary. For those who might delay, it's important to recall that it's vastly easier to build security into an application than to try to retrofit it.

AJAX (asynchronous JavaScript and XML) does great things for Web pages. It has a key trick -- changing pages incrementally -- that does great things for Web page responsiveness and overall user experience. Unfortunately, the technology lends itself to insecure development shortcuts.

AJAX security recently came under scrutiny at the recent AJAX Experience conference in a talk by Douglas Crockford, creator of JavaScript Object Notation (JSON).

Crockford led off with a sobering litany. Web development generally suffers from weak foundations when it comes to security, with an inadequate browser security model. JavaScript, along with most development languages, is not a secure development language. The Document Object Model (DOM) itself is not secure. If you give an untrusted app access to one element, it makes the entire tree insecure.

"How do we build secure apps using insecure pieces?" Crockford asked.

Crockford answered his own question with the concept of trust boundaries. Each object has a trust boundary; it's only allowed to communicate through a very specific interface, preventing one object from messing with the internals of the other object.

A browser page has no trust boundaries within it, which means you shouldn't put scripts from another party in a page, because there's no way to secure the page. Yet often you want to have a widget from one site do useful interactions in another site, despite the fact that currently a good security model isn't supported in the browser.

HTTP provides a natural trust boundary, but Crockford said that having your server trust the browser to make sure data doesn't get delivered to the bad guys breaks a natural security model, which many people circumvent to no good advantage.

Avoid the Same Origin Policy Trap
Some developers use Same Origin Policy to provide security. This places restrictions on access to assets from other sites, but places no restrictions on sending, only on receiving. It also prohibits some useful actions, while permitting some dangerous ones. Crockford called same origin policy "a boon to idiot IT managers who rely on firewalls instead of authentication." Browsers run on computers within the firewall, potentially enabling them to talk to anything else in the firewall. The browsers could be touched by bad Web sites delivered through bad pages, and you're off and running.

According to Crockford, poorly designed security measures lead to circumvention. The measures prevent useful activity. Developers are required to produce useful activity. As a result, they circumvent the measures, even though there are serious penalties for data leakage -- even criminal penalties.

Yes, the Web is significantly safer than desktop apps, but it's not safe enough, Crockford said. Take cross-site scripting (XSS, also known as CSS) attacks. Some evil JavaScript gets into your page. Remember, all scripts look the same to the browser. Foiling this requires good hygiene. Crockford recommended using correct encoding on everything. You can't just take some text and slap some quote marks on it. Servers must do white box filtering on all user-submitted content. Crockford has seen some users unintentionally subjecting themselves to attack by putting widgets or some such on their sites.

Fending off the bad guys starts with rigorous coding. Loose code sinks apps, and lets in not just XSS but cross-site request forgeries as well. Cross-site request forgeries up the ante on XSS by injecting evil code into the Web site. Using cookies to authenticate requests won't stop this. They were never intended to be used as an authentication mechanism, despite their widespread misuse as one. Crockford's solution is using shared secrets in the request in addition to (or, better yet, instead of) cookies.

The database layer of your app could be vulnerable to SQL injection, which exploits poorly filtered or incorrectly typed user input. Crockford recommended extreme caution in building query text from external content, and dismissed remote SQL as "madness. Never expose SQL to the network."

Use JSON for AJAX App Data
As you might expect, Crockford called JSON the best data format for AJAX apps -- safe and effective, but "like everything else, dangerous when used recklessly." For example, you might be tempted to use the dynamic <script> tag hack. This lets the page access data from any server in the Web, which is really useful. However, the data comes back as in a script, which can deliver the data, but runs with the same authority as scripts on the base page. This enables the script to steal cookies or misuse the authorization of the user with the server. A rogue script can do destructive things to the relationship between the user and the base server. The unrestricted script tag hack is the last big security hole in browsers.

Scripts are exempt from Same Origin Policy, enabling a dynamic script tag to make a GET request to a server. And you can't assure that the server didn't send an evil script instead of the data you wanted.

Next Crockford tackled eval. JSON text is JavaScript, so eval can turn it into data structures. This is fast and convenient…and dangerous.

myData = eval('(' + jsontext + ')');

If the text isn't actually JSON, an evil script can execute. Crockford's solution was to use the string.parseJON method.

myData = jsontext.parseJSON();

Evil script will cause a syntax error exception. According to Crockford, this method will be standard equipment in the next version of JavaScript. Fortunately, you can download the update now here.

Crockford had two more practical tips to offer. First, he dealt with the fact that servers accept GET requests with cookies. This runs the risk of data leakage. A rogue page can send a request to your server that includes your cookies, and browsers have holes that deliver data regardless of Same Origin Policy. His solution was to require POST as well as explicit tokens of authority.

Next, he advised developers never to wrap JSON text in comments. Developers may do this to close a browser hole, not realizing that it may open a new hole.

"Security is not obtained by tricks," he said. His basic rule of thumb is never put data on the wire unless you intend it to be delivered. And don't rely on Same Origin Policy.

Of course Web security may improve in the future. Crockford expressed hope for implementation of trust boundaries and conduits between trust boundaries. He said good research was going on at IBM, Microsoft, HP, Google, Yahoo and elsewhere. And he predicted development of a discovery and messaging system that can safely deliver data across trust boundaries, plus connections between pages, iframes, worker pools, desktop widgets and Web services.

YAS Demonstrates AJAX-Era Security
Crockford then introduced Chip Morningstar of Yahoo!, who described a secure application framework using today's technology. It's called the Yahoo AJAX Server (YAS), featuring context and session architecture, with secure session protocol using JSON and HTTP. It's optimized for apps with real-time interactivity, a strength of AJAX -- anything with short-lived session state on the server. The server supports the kind of multiple user interactivity needed for applications such as chat, presentations and games. It also supports server-initiated events, such as alerts, auctions, process monitoring and games again.

Morningstar pointed out that these apps are all awkward in a standard Web server. Unfortunately, the demo didn't work, so he couldn't demonstrate the functionality. The demo was supposed to show stateful sessions over HTTP, JSON messaging, contexts defining applications, multiple user interactivity and server-initiated events.

"Our most powerful tools are security and encapsulation," Morningstar said, "even though the Web paradigm says 'abandon encapsulation'," which REST (representational state transfer) dogma actually elevates to a virtue. On the contrary, YAS represents a scheme to get encapsulation back. This is something Morningstar claimed was needed even more in today's world of Web 2.0, AJAX and mashups.

YAS keeps session state in the server's memory, in opposition to conventional Web-scaling paradigms. Some of those paradigms keep session state in the browser, cookies, form vars and URLs. However, Morningstar saw these approaches as clumsy, insecure and limited in capacity.

"Your data is in the hands of the enemy," he said.

Other paradigms keep session state in a database, which he characterized as clumsy, slow and inefficient. And it reintroduces the bottleneck that motivated a stateless architecture in the first place.

Morningstar proposed scaling differently. Keep the session state in RAM on the server. Scale by session, not by page. This way, the browser just keeps talking to the same server. On the other hand, the Web infrastructure isn't optimized for this, but it's not all that hard to do. Just route by session rather than by HTTP GET request. Have the application page server act like a session-level VIP or HTTP director. And now the browser is already handshaking with the server anyway.

Despite the lack of a live demo at the talk, the session included the kind of practical information needed to back up a view of AJAX-era security that flouts conventional thinking.

About the Author

Lee The's first computer was a state-of-the-art unit with 48K RAM and a 1MHz processor. He has been writing and editing computer magazine articles since then, in between scuba diving trips. He's based in the San Francisco Bay Area.