- From: Thomas Roessler <tlr@w3.org>
- Date: Wed, 5 Dec 2007 09:44:29 +0100
- To: public-appformats@w3.org
I've had a look at some real-life Widgets during the last two or three days and, as a result of that, would have some input to the security considerations. Or rather, I'd like to suggest a section (or a note) on good practices for Widget (and, in fact, Web application) development. (Note that much of this also applies to Web applications that run in a browser and reach out to multiple origins to obtain data. Based on what I've seen in the last couple days, I've come to believe that we're in for some interestingness in that area, too.) Actual widgets look pretty bad in terms of code quality. The Twitter widget issues I described last are really just the tip of a rather large iceberg. There are more vulnerable widgets, and more severe vulnerabilities. However, in this message, I don't want to focus on individual examples, but rather on what this group should do. Here are some of the things to discuss in terms of development good development practices; I'm sure this can be organized much better: - The traditional Web programming model in which (a) the sandbox keeps any security issues in check, and (b) your server-side Web application needs to validate the data anyway (and you can therefore be sloppy on the client) doesn't hold any more. The JavaScript code is the trusted Web application now, and the server is untrusted. - Widgets may or may not have access to local capabilities. There might be some way for them to ask for limited capabilities. If that is the case, Widges should be written in a way that demands only the capabilities absolutely necessary (least privilege). They should avoid using (or getting access to) facilities such as the MacOS widget.system API, which effectively gives the widget full user access to the computer. - When widgets run with privileges that extend beyond the browser sandbox, and if they reach out to the network, then they are effectively custom-built network clients. They must treat any data received from the network as untrusted information, and they must be paranoid about what they do with that data. One particular example is that you shouldn't just run eval on JSON data that you get from "home" (or from another source); you shouldn't insert script tags into the widget's DOM to request third-party JSON data (use XHR and a custom parser instead). Also, if you want to display Web pages, don't download them and render them by dropping them into the Widget's own DOM. Make sure they run in a separate DOM. (E.g., by using openURL.) - Widgets are susceptible to a client-side equivalent of cross-site-scripting attacks: If data retrieved from the network is written to the widget DOM in a way that can cause the uncrontolled creation of elements, then an attacker can once again take over the widget. Techniques such as writing to the document using the Document.write() method or the (not-standard) innerHTML property are particularly risky. These should not be used; instead, text nodes can be created more safely using, e.g., the Document.createTextNode() method. Code insertion attacks are also possible when creating attributes; it is good practice to *not* use data retrieved from the user or (more importantly) the network when, e.g., constructing event handlers for an attribute that's dynamically written. Note that, if widgets run with privileges beyond the traditional browser sandbox, the results of this attack vector be severe enough to be a convenient vector for causing a system compromise. The last point is incredibly important (and *very* easy to get wrong when programming in a certain style); I'm currently waiting for a major vendor to fix a bug like this in one of their widgets, and will then have a juicy example to talk about. I frankly anticipate this to be a source of attacks against widgets for some years to come. In fact, there might be a way to mitigate the "cross-site scripting" side of things that could be attractive to spec and deploy: What if vendors were to put a bargain into code in which the use of innerHTML, Document.write, and friends, or the insertion of script tags which load a script from an external source would tie the Widget to the traditional browser sandbox model? There are at least two ways to do this: - Restrict future JavaScript method invocations to the traditional sandbox model once the risky coding style has occured (i.e., innerHTML, document.write, ...). This is most likely to have the least impact on existing widgets; however, from a programmer's perspective, it is likely to lead to a certain amount of pain, and to hard-to-debug bugs. - Throw a security exception if any of the risky techniques are used in a Widget that has access rights beyond the traditional sandbox. That would be feasible for some of the currently deployed engines, but certainly not for all of them. (E.g., the dashboard widget engine has somewhat finegrained control, whereas the Windows Vista sidebar engine doesn't seem to.) I'd like to see discussion of this some time soon, and will follow up with some examples -- the risky techniques are really all over the place. Having anonymized descriptions of some example flaws and the attacks that work against them would probably be a useful thing for such a security considerations section. Incidentally, most of these considerations also apply to Web applications that mash up data from *different* origins; the same-origin policy indeed has the side effect to localize the consequences of bad client-side scripting. Once again, I wonder if it would be worthwhile to reduce the attack surface by creating a need for a client-side declaration that a script intends to go beyond the traditional sandbox, and (if that is done) trapping of document.write and friends with security exceptions. (I'd love to trap eval() the same way, in fact, but that's far beyond just manipulating the DOM. Still, might be worth thinking about.) Cheers, -- Thomas Roessler, W3C <tlr@w3.org>
Received on Wednesday, 5 December 2007 08:44:42 UTC