GWT: Advanced AJAX Security
Billy Hoffman gave a talk on advanced AJAX security at the recent Google Web Toolkit (GWT) conference in San Francisco. Hoffman manages HP Security Labs, which was SPIDynamics until HP acquired it this year, along with Hoffman. He focuses on automated discovery of Web application vulnerabilities and Web crawling technologies.
His research includes areas such as sampling, JavaScript static analysis (automatic analysis of source code), and cross-site scripting (XSS) -- code injection by malicious Web users into Web pages viewed by other users. However, he did note that XSS isn't required for AJAX hacking; there's much lower-hanging fruit.
In this talk, Hoffman demonstrated advanced attacks against AJAX applications, including manipulating client-side logic, defeating logic protection techniques, function hijacking (client-side code being changed), JavaScript Object Notation (JSON) hijacking and denial of service attacks. He discussed the susceptibility of GWT applications to these kinds of attacks and compared GWT security features to other AJAX frameworks, such as Prototype and Dojo. He ended by talking about hacking Google Gears, an open source browser extension that lets developers create Web applications that can run offline.
Hackers Love AJAX
According to Hoffman, AJAX is a hacker's dream come true. It offers an increased "attack surface," direct Application Programming Interface (API) access, vulnerability to reverse engineering, susceptibility to amplifying Web attacks and vulnerability to offline attacks. He said Microsoft is the worst at opening the door to hackers because nearly everything with Structured Query Language (SQL) statements is SQL-injectible, allowing direct access to the database server. Plus, he said, "much expert advice is blatantly wrong."
Hoffman demo'd what he was talking about in the form of a sample AJAX travel Web site, Hacker Vacations.com, "Where You Can Name Your Own Price." The site lets you find flights and place bids on seats. He built it using "expert" advice from popular books, how-to articles and forums. Nothing bad was cooked on purpose.
Hackers Love Firebug
Hoffman showed how the Web site was riddled with typical security defects. He looked at the underlying code using Firebug. "It makes my job [as a hacker] so easy," he said. This free tool lets you edit, debug, and monitor CSS, HTML and JavaScript live in any Web page.
He used Inspect for FindFlights, showing that you cannot trust that anything you put in the client will hide your code from even amateur hackers. He hit "CTL-U" to see "hidden" source, and then inserted a breakpoint in the code. Then, using Firefox, he unearthed a giant dataset table that got returned underneath the "available flights" actually displayed.
"I just got access to more flights than the app is supposed to give me access to," he explained. He then was able to manipulate the AJAX calls to hold particular seats.
Hoffman said a client-side pricing attack was done in 1997 against CD Universe, in which a hacker was able to buy CDs for one cent for three months until the scam was discovered. Hoffman did the same thing with seat pricing on his demo app, pointing out that "I can tamper with variable values while they're being used in Web 2.0."
In Web 1.0, such functionality was mapped in the server. But now it's being pushed to the perimeter. It gives attackers a blueprint of how to use your app.
Hackers Love Granular APIs
Hoffman calls it the "API Domino Effect." He uses Firebug to look for the callback function to see what's coming back from the server. In this way, he gains access to holdSeat(flightID), thence to makeOffer(price,flightID), thence to bookSeat(flightID) and finally to pay dirt: debitAccount(price).
From a security viewpoint, the APIs are too granular, with too much exposed on the client. Coders will throw everything into one file, and then reference it from parts of the Web site that are public. He showed a real-world example that let him use SQL commands to get valuable passwords, and how an exposed administrative API let him get into SetPrivateData on the server when he was supposed to only be able to access GetPublicData.
Obfuscation and Lazy Loading Won't Guard Code
Next Hoffman showed how hackers defeat logic protection through obfuscation, which encrypts code, and lazy loading, which defers object initialization until the time it's needed. He showed how easily some obfuscation can be disambiguated using a JS parser he'd written. He did concede that Firebug can't debug dynamic code, including JSON responses, remote scripting and lazy loading. It's a matter of "view source" versus "view generated source." Consequently, you need a way to monitor JavaScript environments.
The key is understanding JS variables. Essentially, everything is an object, including primitives and functions, Hoffman said. All global variables and functions are properties of a global object, and the Web browser provides a window into these objects. Hoffman's HOOK JavaScript Monitoring Framework (which a smart hacker could replicate) lets him enumerate the environment and trap on-demand code. It also sidesteps obfuscation by reading from the environment itself.
He also attacked what he calls the myth of the same origin policy, which claims that "same origin restricts" prevent JavaScript from seeing third-party content. In fact, it only does so partially, he said.
Stop JSON Hijacking
Then he discussed JSON hijacking, showing how hackers use remote scripting to read JSON Web services. To defend against this, he said that XMLHttpRequest can see a response and perform operations on it before eval()ing. This frustrates, say, a <SCRIPT SRC> that a hacker might use to point to a JSON Web service and harvest the data that comes back. With this defense, the script is foiled. Then you make the JSON response nonvalid JavaScript. XHR (XMLHttpRequest) removes it, and <SCRIPT SRC> fails.
In general, Hoffman says that if you want to secure AJAX applications you must do six things:
- Perform authentication/authorization checks on both Web pages and Web services.
- Group code libraries by function.
- Validate all input for your application, including HTTP headers, cookies, query string and POST data.
- Verify data type, length and format.
- Always use parameterized queries.
- Always encode output appropriately.
He wound up by touting the new book he coauthored, Ajax Security. He certainly made a case for AJAX developers thinking long and hard about this topic.