JavaScript, Security

Ajax Security, Part II: Attack Surface

Today I pick up from part 1 and discuss one of the challenges in Ajax security: attack surface.

Attack surface describes the points of entry that an attacker can abuse to compromise our application. When writing software with security in mind, we try to minimize attack surface to reduce the likelihood and the impact of successful attacks.

One straightforward way to reduce attack surface is to remove features that are not used or that pose too great a risk. If the code isn’t there, it can’t run so cannot be exploited. Another technique is to reduce the number and complexity of exposed entry points. In web applications, the most obvious entry point is the HTTP interface. This is where Ajax comes in.

Ajax & Attack Surface

Almost by definition, Ajax applications have an larger attack surface than their non-Ajax counterparts. The reason is simple: there are more server-side services exposed — i.e. more URLs. URLs are web applications’ exposed APIs, and Ajax apps make more of them available to end users.

Why? Ajax code needs to talk to something on the server, and usually that means exposing an additional functional URL. Take Google Suggest for an example. As you type in the search box, your browser is making HTTP requests behind the scenes to http://www.google.com/complete/search (I’ve left off query parameters). When you submit the form, it goes to http://www.google.com/search as usual. So to introduce an Ajax feature, Google has exposed an additional entry point to their application(s).

Let’s use a more detailed example from an app that I’m working on, a course search. It’s simple enough, really, there are three basic pages: a form where students enter search criteria, a search results page, and a course detail page for each of the results. The URLs (minus query parameters) might look something like this:

/search/
/search/results
/search/detail

To be clear, I should add some reasonable query parameters:

/search/
/search/results?subj=english
/search/detail?courseid=34512

There are lots of ways we can introduce Ajax to these three pages that make it a little bit easier for the student to use. One is to remove the extra step of looking at course details on a new page. When a student clicks on a course title to get detail, instead of following the link to /search/detail, fire off an Ajax request to get the details and display them in situ, right on the results page. That way the student doesn’t have to keep going back and forth between search results and course detail, and can more quickly find course that interests her.

Here’s the question we face: what is the URL the Ajax code’s HTTP request? A few possibilities:

  1. /search/detail?courseid=34512. The problem here is that normally the response to this request will be an entire HTML page, complete with page headers, footers, navigation, etc. We don’t want all that stuff, we just want the course detail. This will not work.
  2. Same URL as the first option, but with an additional HTTP header that indicates that this is an Ajax request. The server-side code looks for this header and responds accordingly. Prototype adds a custom header X-Requested-With: XMLHttpRequest, which is great but if you ever move away from Prototype you’ll either need to adjust your JavaScript to add the same header or change your server-side code to look for something new. Not necessarily an onerous task, but it’s worth considering.
  3. /search/detail?courseid=34512&output=json. Here we’ve added a query parameter to tell the app to respond with JSON instead of a complete HTML page. Yahoo! does this for their REST web services. We could just as well have added output=xml our output=html to get XML or just the HTML to add directly to the DOM. This isn’t too bad a way to go, but we’ll want to find a way to avoid repeating the code that looks for the output parameter.
  4. /search/detail-ajax?courseid=34512. Use a different page name entirely. This way it’s easy to spot what’s going on, but it seems a little clumsy, especially as you add more Ajax-responding URLs. If you’re using a framework like Struts & Tiles, this is probably the easiest way to go, because you can point to the same Action but use a different set of Tiles for the output. On the other hand, your config file can quickly get pretty large.

If you choose option 3 or 4 (especially 4), you’re introducing new URLs to your app, thereby creating new points of entry and increasing your attack surface. Heck, even for option 2 you’re now relying on a new HTTP header. Never forget that HTTP headers are inputs to your application that need to be examined and carefully validated.

That’s just one example on a single page: I didn’t even mention all the possibilities for Ajax on the search form itself, dynamically creating or updating form fields based on selections made in the form. With the addition of each new Ajax feature, I’ve expanded the possible ways (permissible ways, really) of interacting with my application, increasing the amount of work my server-side code needs to do and the vigilance I need to bring to developing and reviewing the design and code.

Toolkits & Frameworks

I’ll write more about toolkits in a future entry, but I do want to mention now that server-side integration toolkits like DWR are good examples of increasing attack surface. With DWR, you can configure specific classes and methods that you want to expose via JavaScript, and DWR generates the JavaScript as a remote interface to your Java classes. I believe that CFAjax works in much the same way (heck, if memory servers it’s unapologetically a DWR port), as do many PHP Ajax frameworks. Every one of these interfaces is an extra API to your application that you are exposing, making your attack surface that much larger.

I haven’t researched this carefully, but some PHP Ajax frameworks have historically had bugs that permitted arbitrary code execution. Needless to say, this expands the attack surface a bit. :)

Client-Side Business Logic

The Ajax example that I gave earlier is a simple enhancement, but many Ajax apps, as opposed to Ajax-enhanced web apps, are moving more and more business logic to the web browser. This has subtle and not-so-subtle effects on state management, as I’ll explore in an upcoming entry. It also means that there’s a lot more code available for an attacker to play with.

I have encountered a strange, unstated expectation among some developers that once JavaScript code is sent out to a client, it’s untouchable. This seems to be especially the case with code generated by a framework. I’m not sure where this idea comes from, and I hope it crumbles with even the slightest examination, but it’s out there. And it’s flat-out wrong.

You don’t, for example, want to do things like send SQL queries in your Ajax requests. I swear, I actually saw this in a web app a couple weeks ago. I happened to have LiveHTTPHeaders open while I was surfing and saw a SQL statement scroll past. I investigated and sure enough, the server was executing whatever arbitrary SQL was sent to it from the browser.

The developer didn’t need Ajax, of course; it could just as easily have been a submitted HTML form. Still. Do not do this.

Another effect of moving more Ajax code onto the client is that there are new trust boundary concerns. As you know, input validation is essential to web application security. Software security in general, really. Any time data passes across a trust boundary, where you don’t entirely trust its origin or integrity — data submitted from a browser to a web server, for instance, or from a remote web service or a database to your application code — it is important to perform rigorous input validation. We are (hopefully) used to this. It ought to be second nature.

Let’s make this clear: we’re used to this on the server side, working in a trusted environment accepting untrusted input.

In Ajax apps, though, lots of data is being passed back and forth between client-side and server-side code. If there’s significant business logic running in the browser, it stands to reason that the browser should validate data that crosses a trust boundary on its way from the server. Here’s the thing, though: while on the server side our code runs in a trusted environment (or what we hope can be trusted), in a browser our code (or what we hope is our code) runs in an untrustworthy environment accepting untrusted input. In the past, we’ve more or less assumed that we could trust what came from the server. We learn from Amit Klein that we should not: the communication channel between the client and server is vulnerable and suspect.

The conundrum is of course that the code that does the validation is completely exposed on the client.

One thing to watch out for is blindly eval()ing JavaScript. As I wrote in part 1, the server response to an Ajax HTTP request is typically either XML, JavaScript, or HTML. Nowadays the JavaScript is usually JSON, which looks like this:

{
"birthdays":
[ {"name":'Abe Lincoln',    "bday": "12 February 1809" },
{"name":"James Buchanan", "bday": "23 April 1791"}]
}

Here’s a common way of using that response.

var obj = eval( '(' + res.responseText + ')' )

The risk here is that the server response may contain malicious code. If you blindly eval() the response, you’ll immediately execute that code. You can mitigate the risk by using a JSON parser to at least ensure that it is indeed JSON.

var obj = resp.responseText.parseJSON();

This is of course far from a perfect solution. I confess that I am not sure how best to handle this. I need to do more thinking and more research. Pointers are welcome.

Web 2.0 Meets SOA

As more and more business logic pushes out to the browser, it is tempting to have that client code connect directly to web services in a service-oriented architecture (not that you need web services for SOA, but bear with me). JavaScript can do SOAP, so why not? The problem is that often those services are thin wrappers around 20-year old COBOL code. You don’t want to be exposing this to the world. Andrew van der Stock discusses this in interview for SearchAppSecurity.com.

I don’t have a problem with JavaScript making web services calls using SOAP, REST, XML-RPC, whatever. Keep in mind, though, that the browser environment cannot be trusted, so any validation or access control you’ve put in place there doesn’t do any good. If the value of the transaction is high — e.g. if it needs authentication at all — or if the code behind the service was written with the expectation of running in a completely trusted environment, then you’re far better off minimizing exposure by providing carefully controlled and monitored access to that code. Meaning, don’t allow anyone in the world to connect to it: limit access to code running on your server. If you want to use JavaScript to access the service, have it contact another service that’s tied into your access control mechanisms.

Resources & Further Reading

I’m not pulling all this out of thin air. Much has been written on the topic of Ajax security. A lot of it FUD, but there is some very worthwhile reading out there that I’ve used to inform my own research and writing. Here’s some of it:

Mitigate Security Risks by Minimizing the Code You Expose to Untrusted Users
An article about attack surface reduction by Michael Howard
Ajax Security
A presentation at AppSec by Andrew van der Stock.
OWASP Guide 3.0
The new version of the Guide to Building Secure Web Applications has a draft chapter on Ajax security.
Ajax security resources
At cgisecurity.com.
del.cio.us/afongen/ajax+security
Rather than just duplicate more links, I’ll send you to my del.icio.us links.

Coming Up…

Next time, we’ll look at another challenge in Ajax security: state management and access control.

JavaScript, Security

Ajax Security, Part I

“Did you see 1 Raindrop today?” a coworker asked, referring to something Gunnar Peterson had written about Ajax security. I went off on a little rant about how yes XMLHttpRequest exploits are interesting and Amit Klein’s work is marvellous, but XHR can be used in an exploit regardless of whether a web app actually uses Ajax, that from a development perspective the approach is the same: we’re accepting requests from an untrustworthy client, so we need careful consideration of security throughout the development lifecycle, solid input validation & output escaping, session management, access control, and so on.

He waited patiently and smiled knowingly. “Yes, Sam, but you are already thinking about these things.”

Ah. As I also frequently complain, thinking like this is still unusual. That’s why software security is such a problem.

So I started looking around to see what was happening in the Ajax security space. It isn’t pretty, but the Ajax angle to the security problems is as overhyped as Ajax itself. There’s been a fair amount of discussion/coverage worth reading, including a new chapter in the OWASP Guide 3.0 draft. Gunnar’s post points to work by Amit Klein that I highly recommend.

On Tuesday I gave a short and overcaffeinated talk about Ajax security to my local OWASP chapter. To follow up on that, I’m starting a series of posts here addressing the topic in greater detail.

Executive summary: in the rush to add Ajax functionality to web applications, security is being disregarded or included as an afterthought (which often amounts to the same thing). Ajax itself isn’t insecure, but it sure can be unthinkingly misused and made insecure. Ajax can make other attack vectors like cross-site scripting and cross-site request forgeries worse, whether or not you actually use it in your application. As it has recently been made clear, XSS is far worse than we’ve thought, so it is important to be careful.

My position is actually a little more nuanced than that, and may well change as I write here. We shall see.

Quick Intro to Ajax.

You may already be familiar with Ajax, especially if you’ve read this far without being bored out of your mind. But just so we’re all on the same page, let me take this opportunity to show off a little Flash demo that my colleague Dave Kruse whipped up over breakfast just before an Ajax presentation that we were about to give.

You know how web applications have traditionally worked. Your browser makes a request to a web server, and the server responds by returning a whole new web page.

(For now, until I add some JavaScript to dynamically show/hide the animation, here’s a link to the first demo Flash movie. Thanks to Dave for his permission to use this here.)

With Ajax, your browser makes a request and the server responds, but this time with a small snippet of data that is used to update just a section of the page. No need for a full page reload.

(Link to the second Flash movie.)

Two key elements to this are that we are using JavaScript to make HTTP requests and to update the HTML page. We’ve actually been able to do this for some time, but in Ajax we can more easily manage the HTTP request and response using an object called XMLHttpRequest. The response from the server is usually one of the following:

  • XML, which is parsed by JavaScript to generate the (X)HTML to add to the web page;
  • more commonly we’re seeing JavaScript, which is eval‘d and run. JSON is a popular way to do this.
  • the actual HTML that will be added to the page.

Ajax use in web applications falls along a spectrum ranging from small usability enhancements such as auto-populating a drop-down without reloading the page (dubbed by Harry Fuecks as HTML++), to mopre full-blown client-side apps, where lots of business logic is in JavaScript on the browser. How you choose to use Ajax will affect your security posture, as we will explore in future posts.

Ajax Security

Fundamentally, Ajax is no different when it comes to web application security. We have the same concerns:

  • We’re dealing with completely untrustworthy clients.
  • Input validation is essential. From the perspective of server-side code, requests are coming in from anywhere — untrusted clients, remember? — and we need to be sure that the data in the requests is what we expect.
  • Escaping output, nothing new there.
  • We have to pay careful attention to session management and access control.
  • Code injection is a problem. JavaScript, XML, LDAP, DOM…
  • The list goes on. See resources at OWASP. There’s even a new Ajax chapter in version 3 of the OWASP Guide.

That said, developers (and architects, too, don’t let them off the hook!) are making security mistakes when they introduce Ajax to their applications. I don’t blame Ajax for this: the real danger is JavaScript that operates in a browser environment, allowed to make HTTP requests and modify the DOM, and web apps that allow this to be abused easily. Actually, the real danger is that software security is too often an afterthought. For some reason, the rush to use Ajax has led to developers placing too much trust in client-side code. What worries me most about this is that at separate presentations at last week’s Black Hat, Jeremiah Grossman and Billy Hoffman described a new spate of JavaScript malware that takes advantage of XSS and CSRF vulnerabilities to do some seriously scary stuff. Grossman describes XSS as the new buffer overflow. Ajax isn’t necessary for some of the techniques described, but it can make an XSS attack worse — whether or not you use it in your web apps.

So what’s different about Ajax from a security perspective? I’ll take that up in the next entry.

Personal

Another scene from my life with Owen

Today at dinner:

Me: Ooh, your glass is empty, would you like more water?
Owen: When a bird dies, we all suffer, too.

It’s like I’m living with a Zen master.
We recently checked out a book about endangered animals, and it’s affected him deeply. We returned it days ago, and he’s still mulling over the text (which he’s apparently memorized) and asking thoughtful questions.

Security

Cross-Site Scripting Tutorial Podcast

Dan Kuykendall has posted a cross-site scripting tutorial over at the MightySeek podcast. If you don’t understand cross-site scripting or have a shaky understanding, I recommend it. Dan suggests that while listening you follow along in the show notes and actually try the attacks on a sandbox he’s set up at hackme.mightyseek.com. I didn’t do this, but if you’re new to XSS then it’s probably a good idea to learn by doing.

Coffee

Grind Only What You Need

If you are or know a barista, here’s a tip: grind the espresso as you need it. Don’t let the grinder run until you’ve got half a pound of pre-ground espresso sitting around getting stale. Seriously. If I see you doing that, I’ll just walk out.

The reasons are myriad, but it all comes down to quality. Not only does prolonged exposure to oxygen make coffee go stale, ground coffee absorbs moisture from the air and swells. Espresso is very finely ground, about as fine as table salt. If it swells, the extraction will be all wrong. If it’s stale, then what’s the point?

With espresso more than most other methods of coffee preparation, details matter. There’s not a lot of room for error. The beans need to be fresh, but not too fresh. The grind needs to be right for the air conditions. The ground coffee needs to be tamped properly (not too hard, not too light). The water quality, temperature, and pressure are critical. The length of extraction — how long water is in contact with the grounds — is a deal breaker. It must be consumed soon after brewing. Mess up any one of those elements and you’ve ruined the experience. It’s the experience of espresso that sets it apart.

So please: you might think it’s saving time or wear on the grinder to pre-grind the coffee, but it’s not worth it.

Java, JavaScript, Ruby

Rhino + JLine + Dashboard… nice.

On a tip from Todd Ditchendorf, I’ve had JavaScript and Ruby interactive shells running in Dashboard widgets for some time now. It’s fan-frickin-tasic. If you do anything with Ruby you probably already spend a fair amount of time in irb, and I imagine that Python programmers also understand. But it’s a fair guess that few JavaScript programmers are firing up a JavaScript shell to, say, test a regular expression. Maybe that will change with Java 6 adoption, since it has a native, defined API for interaction with dynamic languages.

Having the shell just a keystroke away is a huge help, all through the magic of WidgetTerm.

In “Taming the Rhino: Making Mozilla’s Javascript Command Line a Little Less Brutish”, Charles Lowell suggests using JLine to bring Rhino’s shell up to snuff. I have to admit, not having history is a pain in the butt. So I’ve dropped the JLine jar into ~/Library/Java/Extensions so it’s in my classpath along with Rhino’s js.jar, changed my js alias to java jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main, and life is a tiny bit sweeter. Thanks, Charles!

Java, Security

Generate new session ID in Java EE?

Is there a Java EE equivalent to PHP’s session_regenerate_id()? I’d expect to find it in the neighborhood of HttpSession but don’t.

I like to change the session token whenever there’s a change in a user’s privileges. For example, let’s say that Suzy is surfing a site anonymously for a while before she logs in. As an anonymous user, she has pretty low privileges. Then when she logs in, she has greater privileges on the system. Maybe she can view her home address, update billing info, or heck: maybe she has administrative access. There has been a change in access level.

A problem arises when while surfing anonymously with low-level access, Suzy’s session ID is stolen by an attacker using cross-site scripting or session fixation. After Suzy logs in, the attacker now has the same increased privileges on the system that Suzy does, because the attacker has Suzy’s session ID.

One countermeasure to session fixation attacks is to change Suzy’s session ID whenever her privileges change. When she logs in, assign her a new session ID. When she logs out, assign her a new session ID. Each time Suzy gets a new session ID, the old session is invalidated and the attacker — who has the old session ID — is left with an useless (nonexistent) session.

PHP’s session_regenerate_id() does this transparently, copying over session data to the new session each time (although the implementation is not without its problems). The truly crazy can even do this on each request. If I’m not mistaken, ASP.NET 2.0 also offers a means to generate a new session ID, though maybe only with cookie-less sessions. Java EE does not appear to at all. Maybe some servlet containers do, but it’s not in the spec so far as I can see.

Yes, I can always create a new session and copy over all the attributes to the new session before invalidating the old one. No, it isn’t that hard. I’m just wondering if there isn’t a way for the container to do this instead. Anyone know?

Security

OWASP meeting August 8

Next Tuesday, August 8, the Minneapolis / Saint Paul OWASP chapter is meeting at Metro State Management Education Center in downtown Minneapolis, right near MCTC. Directions are on the chapter page.

I’ll be presenting a short talk on Ajax security. Then Pete Palmer from Wells Fargo will talk about “Making the Most of Apache Web Server Security”. I don’t know Pete or anything more about him than his brief bio, but I’ve been told that he’s an engaging speaker.

There will be pizza.

If you’re in town, I hope you can make it. The group is really starting to come together.

Site

Switched to WordPress

I finally got around to switching to WordPress. Two motivating factors:

  • I had been using a seriously outdated version of Movable Type. It was high time to move on, partly because I didn’t trust it anymore, especially if I wanted to enable comments. Not that Movable Type can’t be trusted with comments; I just didn’t feel confident in a really old MT.
  • It was about damn time that I enabled comments. In the five years I’ve been blogging here, I haven’t had comments running. At first it was because I just didn’t want to feel obliged to stay on top of the conversation, then it was because I didn’t want to deal with comment spam. The last year or so, though, I’ve just been too lazy to make the switch. My head has been elsewhere.
  • Make that three factors: freedom zero. Yes, Six Apart learned from that fiasco and updated and clarified their licensing, but in the end open source matters.

The feed hasn’t moved but everything may look new. Sorry about that. Old links should still work, please let me know if they don’t. In the meantime, I’ll be cleaning up small things like making new links work better, adding contact information using hCard over there in the sidebar, locking down a few things that could probably still use locking down, and generally getting comfortable in the WordPress world.

Personal

“They all moved here” (another scene from my life with Kiara)

“All the religious freaks moved here. You know how all the criminals were sent to Australia? You go to churches in Europe and they’re empty because all the goddamn religious freaks moved here.”

I rescued this from a draft blog post two years ago and leave it as an exercise for the reader to determine which one of us said that.

« Prev - Next »