SPICON: Eploiting Ajax Applications

Billy Hoffman - Lead Researcher - SPI Dynamics

Focus today on hacking Ajax. Lots of buzz on Web 2.0.

Traditional app:
Javascript verification on top of HTML that was produced by dynamic data, which was published from backend source. User activity goes back into load/reload cycle. User looks at a blank screen while the user is waiting on the server to perform calculations and render results. Map Quest, for example - whole screen has to refresh to make changes only to the map.

Ajax (XmlHttpRequest) does the calculations in the backend to re-render only necessary portions of the site. Google maps is a perfect example. The trough of the server performing calculations still exists, but the application is still responsive during that time. The requests are still taking place, but only hidden, rendered off screen.

XmlHttpRequest is full-featured - if you wanted, you could do WebDAV if you wanted. Orignation policy - can't do Ajax requests to a different host from whence it came.

Security Issues with Ajax:
Issues with architecture:

  • Information leakage
  • Direct Access to API
  • Increaed attack surface
  • Code complexity
Issues with Ajax implementations
  • Repudiation of HTTP Requests/XSS Amplification (server can't tell the difference between user-initiated or XmlHttpRequest-initiated).
  • Ajax bridges/gateways/proxies
Q: Why can't the server tell where the request came from (auto or user initiated?)
A: We'll see later, but the request has to include all the stuff the browser knows.

Clearing some myths:
  • Ajax doesn't change security
  • SSL protects me
  • User supplied content is awesome
  • Thin clients more secure than thick
  • RAD is a good thing
Ajax actually amplifies info leakage, parameter attacks, XSRF, XSS, SQL Injection.
New attacks that didn't exist before client apps - HTTP request origin issues, business logic leakings, client trust issues, presentation layer attacks, client-side storage attacks.

SSL doesn't protect you - this all happens at layer 7. SSL can actually hurt you - so the attackers get to do all this stuff without being noticed by NIDS (unless NIDS has secret keys, or if you break SSL early).

User-supplied content is dangerous. MySpace, or from a bunch of RSS feeds - information you have no control over is being put together to publish on your own site. You take content from somebody you don't trust and present it in your own security context.

Thin-client vs. thick-client security. In thick client - if I bust the app, I bust my own. If I bust a webapp, it busts for everybody.

The entry level for writing webapps for old-school people is really low - but the frameworks don't do the security for us. (I knew Java already - so writing server-side Java is much easier).

RAD is not a good thing. Build a new webapp in 10 minutes. I can't perform security testing in that amount of time, let alone DESIGN it securely. If the backend SOA components weren't secure to begin with (not necessarily a bad thing), now I expose that to the web, then I've just exposed a vulnerability to the world.

In Ajax, we extend business logic down to the client. Now attackers are inside of the application. Any web services you contact in your Ajax app, the attacker can contact. The trust relationship doesn't matter anymore (i.e., the app layer assumes the data from the server layer is cool because they're both in-house - now when the webapp does that, that trust is no longer legitimate).

Increased attack surface. All the communication that used to only take place between the web tier and the app tier now takes place between the user tier and the app tier. More functions exposed to user. Three types of input to filter: GET/POST form input (we're really bad at this), File formats (images, ZIP files), Exposed functions and web services.

How many web services does the framework expose for you? How do you secure what you don't know.

Input validation:
Should be easy, but we don't do it.

An attacker only needs one mistake. Example of Atlas exposing three web vulns to the user,

Function exporting. Most Ajax frameworks export server-side user functions - even system calls.

Ajax apps are now written in at least two languages - making things more complex. Javascript is loosely typed and higly dynamic.

Stealing from client-side storage. Dojo storage, Cookies, IE's Persistence. FSO doesn't do javascript domain checking?

Presentation layer attacks - using absolute position to swap a from application and a to application.

Request Repudiation. Being able to deny you did something. The browser adds cookies for you, but the server has no way of determining that the request was user-initiated. XSS viruses. Samy, Yamanner. Samy to Yamanner was 8 months. Criminals now are using this stuff.

When we allow you to upload HTML, it's really hard to determine what's safe vs. unsafe.

Ajax bridges/proxies/gateways. XmlHttpRequest can't call domains outside where it came from. Lots of services will do backend third-party requests. Code calls site 1 -> site 1 calls site 2. This type of aggregation is encouraged. Generally any commercial use requires a formal agreement. These bridges just pass on the same kind of garbage.
Vectors: database theft. My amazon key won't allow me to get all the books from Amazon. Billy's books uses Amazon, and his key has a higher permission level (more books, more concurrent requests, etc.) So I can use Billy's books to do my queries to speed up the requests. Attacking third parties through the bridge - send XSS or SQL Injections - other Web attacks through the bridge. Third party notices that something bad is happening, but it's a way for the attacker to hide themselves. What if the third party doesn't even notice?

Design checklist:
Should you Ajax enable in the first place?
Retrofitting an old aplication - document current inputs. Ensure input validation on all existing inputs.
Design Ajax applications - minimize the program logic you need to expose. Implement validation on all function input. Use clear standards, not hacks (SOAP, JSON).