W3C

When Widgets Go Wrong

When I’m curious about tomorrow’s weather (or need a quick look at a calendar), then I’ll often invoke my laptop’s Dashboard: It’s a platform for Widgets, small applications written in HTML, CSS, and JavaScript — Web technology, moved to the local host. These widgets provide front-ends to all kinds of information sources on the Web; several thousand are available for download. Obviously, the use of Web technologies has been a huge success here, enabling people to adapt their programming experience from the Web to their local platform. Apple’s Dashboard is, of course, not the only platform: Google, Yahoo, Microsoft, and Opera have widget (or gadget) engines of their own; W3C’s Web Application Formats Working Group has catalogued the properties of the various platforms in its widgets requirements document, and is working on a standard packaging format for widgets.

With the Web programming platform, though, come the Web’s programming practices and security issues, sometimes with more serious consequences than before.

Let’s begin with a classical piece of bad programming: Parsing data by evaluating it as code. JSON stands for JavaScript Object Notation; it means using JavaScript constant expressions as a way to transport structured data over the network. The easiest way to parse that data format consists in evaluating it as code. JavaScript has an eval() primitive that comes in usefully: It takes a string and interprets it. Now, one can argue that that’s just the same thing as including another script, so it’s not really a big deal when done in the client-side part of a Web Application. The effect is, after all, limited to one application, and that application’s server-side code will have to deal with hostlie clients anyway.

However, while Widgets might feel a lot like the usual Web environment to the programmer, they really aren’t: The limitations on what JavaScript code in a Widget can do are (sometimes vastly) different. For instance, the Dashboard has a widget.system method available; that method takes a string and executes it as a Unix shell script. Effectively, JavaScript has acquired an interface to the operating system. The question what scripts (or widgets) one executes has become the same question as the one what programs one installs. A widget that evaluates JSON data is now a way for an attacker to turn an attack against, say, a service like Twitter, or against your local network, into an attack that takes over an entire machine. That problem isn’t just academic: Unsafe JSON parsing is a regrettably common programming practice among widget authors. And your web browsing behavior is intercepted whenever you’re asked to pay at a commercial wireless hotspot. Exploiting these attacks is easy.

eval() isn’t the only way to create this kind of attack surface: Using callback based JSON programming techniques by inserting <script> tags into a widget’s document object model creates exactly the same kind of vulnerability.

But there’s more: You might have heard of cross-site-scripting vulnerabilities as, for instance, the source of the recent Orkut worm. The problem here is that a Web application takes input from some untrusted source and writes it into the HTML that it generates, without paying proper attention to escaping tags that an attacker might have placed in that input. The attacker can then inject scripts into the Web application’s output, and these scripts can confuse clients’ behavior. Now, what has that to do with widgets? Consider that widgets use an HTML document as their user interface. Any data that are presented to the user are written to the that document by JavaScript code.

That JavaScript code might quite well use techniques like the non-standard innerHTML DOM property to add a large fragment of HTML to the user interface. If the data that are written to that property come from an untrusted source (e.g., the network), and aren’t properly sanitized, then an attacker can once again get scripts executed.

The Google Gmail widget was an example for that kind of code, until quite recently. Here, HTML tags in an e-mail’s subject header were written into the widget’s UI without checking. The effect was stunning: One e-mail with the right JavaScript in the subject header was enough to take over the recipient’s computer, if that recipient was running the Gmail widget. Google has now fixed the problem in this widget.

But Google isn’t alone: There are more widgets out there with this kind of vulnerability. Triggering the vulnerability might not take an e-mail, but involve a network attack, or, maybe, a malicious blog post, a photo description, or some interaction on a social networking site. Or the widget itself might come from a malicious source. The point here is that we’re dealing with a shift in what Web-style programming can achieve — and that that shift does not come without risk, and responsibility. A shift, incidentally, that extends beyond just Widgets, as Web technology is also becoming the programming platform of choice for mobile devices, and as the capabilities of Web applications that run in the classical browser are extended.

Addressing this risk and responsibility will require work both inside the “Web industry” proper (and in the W3C Working Groups where it meets, including the Web Application Formats and Web API WGs), and with the broader community: This is a problem that extends beyond just the platform.

PS: I hope explore this space more at this year’s Chaos Communication Congress in Berlin, and maybe at next year’s Web Conference.