Re: [webkit-dev] innerStaticHTML
On Wed, Nov 25, 2009 at 1:49 PM, Maciej Stachowiak wrote: > On Nov 25, 2009, at 1:33 PM, Adam Barth wrote: >> I don't have a complete design in mind. I could try to write up a >> design document. > > Sounds like we could use one given the potential complications. I've sketched out a complete design here: http://docs.google.com/Doc?id=dd4p8wc4_12sm65qbk4 I've given the participants in this thread write access so they can add notes / ideas. If you'd like write access, let me know. Adam ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 25, 2009, at 1:45 PM, Michal Zalewski wrote: The other way to skin this cat, by the way, is to implement the seamless attribute on iframes. That gives you a similar sort of design using the @sandbox attribute and solves many of your above concerns, e.g. by creating a new namespace for @ids. Maybe we should try that first or in parallel? I would think that in practice, IFRAMEs would, at least psychologically, be significantly less useful to web app developers. This is due to the fact that frames are conceptually more difficult to properly position and size to accommodate any dynamically inserted text; Seamless iframes would address this first problem by participating in the layout of the containing page. are more cumbersome to pre-populate with data on server-side (extra HTTP roundtrips or opaque data: URLs). Also, are renderer implementations actually ready to handle hundreds of seamless IFRAMEs on a page with the performance footprint not exceeding that of spans and divs? But not these last two problems (though I think you can still document.write() into a sandboxed seamless iframe, making it not much less convenient than the staticInnerHTML solution). Regards, Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 25, 2009, at 1:33 PM, Adam Barth wrote: On Wed, Nov 25, 2009 at 1:25 PM, Maciej Stachowiak wrote: On Nov 25, 2009, at 12:34 PM, Adam Barth wrote: On Wed, Nov 25, 2009 at 12:30 PM, Maciej Stachowiak wrote: On Nov 25, 2009, at 6:05 AM, Adam Barth wrote: Maybe we should have a DOM API called webkitJailChildren("no-script-for-you") on Node that prevents future children from running script. Making it a DOM API prevents authors from trying to turn the feature on with markup. Interesting idea. This seems potentially trickier to implement than just innerStaticHTML, since nearly every method that mutates the DOM will have to check jail status. innerStaticHTML could be limited in scope to only operations that happen as part of parsing. Instead of checking every DOM mutation, we could just walk the parent pointers before executing a script to see if an ancestor is jailed. I don't have a complete design in mind. I could try to write up a design document. Sounds like we could use one given the potential complications. A few thoughts: 1) Presumably we'd want to block instantiation of plugins and Java applets too, or the scripting restriction becomes toothless. Perhaps also iframes, unless the scripting restriction is intended to propagate across frame boundaries. Yes. Also the element. Essentially, all the same APIs that are currently restricted by the XSSAuditor. 2) Capturing all points at which script execution occurs and tracing them back to the originating element may be tricky. javascript: URIs are one potentially subtle example. By the time the JavaScript for those gets executed, I believe we no longer know the originating element, the way the code is currently structured. The way I would do this is to teach HTMLAnchorElement and friends not to hand off JavaScript URLs to FrameLoader if their parent is jailed. I'm not sure how many such interception points we'd need. Not sure either. Two others I can think of are SVGAElement and HTMLFormElement. 3) It seems like the rule "don't execute JS" might not be quite what is desired, since it would (presumably) prevent the parent itself from using event listeners on nodes in the jail. IMO the best treatment for event listeners would be to prevent them from being created by attributes, rather than to prevent them from executing. Agreed. We'd want to stop inline event listeners from being created on jailed nodes. 4) Do we need to strip or rename id, name and class values to prevent interference with the containing page's use of getElementById() and such? Caja does. I think this is an order of magnitude less important that direct script execution. There are going to be advanced use cases for which Caja is the right answer. Caja wants to let you actually run script in the jail without interfering with the containing page - I definitely don't think we should target that. But preventing the content from interfering with the containing page seems in-scope. I agree this particular threat is less risky than actual script execution. The other way to skin this cat, by the way, is to implement the seamless attribute on iframes. That gives you a similar sort of design using the @sandbox attribute and solves many of your above concerns, e.g. by creating a new namespace for @ids. Maybe we should try that first or in parallel? Indeed, it can cover some similar use cases. I don't know if it's good for comment sections - one iframe per comment would be quite heavyweight. If there is any active content *around* each comment (like edit or reply buttons) then you might not be able to use one for all of them. In such a case I think innerStaticHTML (or moral equivalent via jailed nodes) would be a more suitable solution. If you have only a small number of untrusted content regions then seamless iframes could be a good solution and it might be easier to be really confident of the implementation (since all cross-frame access of any kind is already doing a security check, and turning off scripting or plugins wholesale for a frame can be done in a very localized way). OTOH it would require render tree expertise to implement the layout aspects. Regards, Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
> The other way to skin this cat, by the way, is to implement the > seamless attribute on iframes. That gives you a similar sort of > design using the @sandbox attribute and solves many of your above > concerns, e.g. by creating a new namespace for @ids. Maybe we should > try that first or in parallel? I would think that in practice, IFRAMEs would, at least psychologically, be significantly less useful to web app developers. This is due to the fact that frames are conceptually more difficult to properly position and size to accommodate any dynamically inserted text; are more cumbersome to pre-populate with data on server-side (extra HTTP roundtrips or opaque data: URLs). Also, are renderer implementations actually ready to handle hundreds of seamless IFRAMEs on a page with the performance footprint not exceeding that of spans and divs? /mz ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Wed, Nov 25, 2009 at 1:25 PM, Maciej Stachowiak wrote: > On Nov 25, 2009, at 12:34 PM, Adam Barth wrote: >> On Wed, Nov 25, 2009 at 12:30 PM, Maciej Stachowiak wrote: >>> On Nov 25, 2009, at 6:05 AM, Adam Barth wrote: Maybe we should have a DOM API called webkitJailChildren("no-script-for-you") on Node that prevents future children from running script. Making it a DOM API prevents authors from trying to turn the feature on with markup. >>> >>> Interesting idea. This seems potentially trickier to implement than just >>> innerStaticHTML, since nearly every method that mutates the DOM will have >>> to >>> check jail status. innerStaticHTML could be limited in scope to only >>> operations that happen as part of parsing. >> >> Instead of checking every DOM mutation, we could just walk the parent >> pointers before executing a script to see if an ancestor is jailed. I don't have a complete design in mind. I could try to write up a design document. > A few thoughts: > > 1) Presumably we'd want to block instantiation of plugins and Java applets > too, or the scripting restriction becomes toothless. Perhaps also iframes, > unless the scripting restriction is intended to propagate across frame > boundaries. Yes. Also the element. Essentially, all the same APIs that are currently restricted by the XSSAuditor. > 2) Capturing all points at which script execution occurs and tracing them > back to the originating element may be tricky. javascript: URIs are one > potentially subtle example. By the time the JavaScript for those gets > executed, I believe we no longer know the originating element, the way the > code is currently structured. The way I would do this is to teach HTMLAnchorElement and friends not to hand off JavaScript URLs to FrameLoader if their parent is jailed. I'm not sure how many such interception points we'd need. > 3) It seems like the rule "don't execute JS" might not be quite what is > desired, since it would (presumably) prevent the parent itself from using > event listeners on nodes in the jail. IMO the best treatment for event > listeners would be to prevent them from being created by attributes, rather > than to prevent them from executing. Agreed. We'd want to stop inline event listeners from being created on jailed nodes. > 4) Do we need to strip or rename id, name and class values to prevent > interference with the containing page's use of getElementById() and such? > Caja does. I think this is an order of magnitude less important that direct script execution. There are going to be advanced use cases for which Caja is the right answer. The other way to skin this cat, by the way, is to implement the seamless attribute on iframes. That gives you a similar sort of design using the @sandbox attribute and solves many of your above concerns, e.g. by creating a new namespace for @ids. Maybe we should try that first or in parallel? Adam ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 25, 2009, at 12:34 PM, Adam Barth wrote: On Wed, Nov 25, 2009 at 12:30 PM, Maciej Stachowiak wrote: On Nov 25, 2009, at 6:05 AM, Adam Barth wrote: Maybe we should have a DOM API called webkitJailChildren("no-script-for-you") on Node that prevents future children from running script. Making it a DOM API prevents authors from trying to turn the feature on with markup. Interesting idea. This seems potentially trickier to implement than just innerStaticHTML, since nearly every method that mutates the DOM will have to check jail status. innerStaticHTML could be limited in scope to only operations that happen as part of parsing. Instead of checking every DOM mutation, we could just walk the parent pointers before executing a script to see if an ancestor is jailed. A few thoughts: 1) Presumably we'd want to block instantiation of plugins and Java applets too, or the scripting restriction becomes toothless. Perhaps also iframes, unless the scripting restriction is intended to propagate across frame boundaries. 2) Capturing all points at which script execution occurs and tracing them back to the originating element may be tricky. javascript: URIs are one potentially subtle example. By the time the JavaScript for those gets executed, I believe we no longer know the originating element, the way the code is currently structured. 3) It seems like the rule "don't execute JS" might not be quite what is desired, since it would (presumably) prevent the parent itself from using event listeners on nodes in the jail. IMO the best treatment for event listeners would be to prevent them from being created by attributes, rather than to prevent them from executing. 4) Do we need to strip or rename id, name and class values to prevent interference with the containing page's use of getElementById() and such? Caja does. Regards, Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Wed, Nov 25, 2009 at 12:30 PM, Maciej Stachowiak wrote: > On Nov 25, 2009, at 6:05 AM, Adam Barth wrote: > > Maybe we should have a DOM API called > > webkitJailChildren("no-script-for-you") on Node that prevents future > > children from running script. Making it a DOM API prevents authors > > from trying to turn the feature on with markup. > > Interesting idea. This seems potentially trickier to implement than just > innerStaticHTML, since nearly every method that mutates the DOM will have to > check jail status. innerStaticHTML could be limited in scope to only > operations that happen as part of parsing. Instead of checking every DOM mutation, we could just walk the parent pointers before executing a script to see if an ancestor is jailed. Adam ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 25, 2009, at 6:05 AM, Adam Barth wrote: On Tue, Nov 24, 2009 at 11:21 PM, Maciej Stachowiak wrote: If we tie it to an element or attribute, people may be tempted to just do it in markup, which would be insecure. Maybe we should have a DOM API called webkitJailChildren("no-script-for-you") on Node that prevents future children from running script. Making it a DOM API prevents authors from trying to turn the feature on with markup. Interesting idea. This seems potentially trickier to implement than just innerStaticHTML, since nearly every method that mutates the DOM will have to check jail status. innerStaticHTML could be limited in scope to only operations that happen as part of parsing. On Tue, Nov 24, 2009 at 11:27 PM, Michal Zalewski wrote: ...unsanitized user content... I'd rather not go this route in our initial implementation. I think we should target the use case of a web site receiving an untrusted string via cross-origin XMLHttpRequest or postMessage. One obvious likely use case is for sites that wish to sanitize user- generated content, for example comment sections of blogs. innerStaticHTML is actually decent for that use case. Not quite as nice as markup, but I'm wary of introducing parser complexity to defend against hostile content that tries to prematurely close the jail. Regards, Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
> I'd rather not go this route in our initial implementation. I think > we should target the use case of a web site receiving an untrusted > string via cross-origin XMLHttpRequest or postMessage. Fair enough. OTOH, this solves a very narrow problem. If we have an implementation that at least extends to a non-JS solution without the need to create a wholly separate mechanism should there eventually be desire to make a difference in this area, it's a win. So, child-locked tags appeal to me a whole lot more than a variant of .innerHTML. Cheers, /mz ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
>>> http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-June/020191.html > I think we should experiment with the minimal API that seems useful. > If the experiment is a success, we can scale it up. Apologies if I am rehashing something discussed earlier, but I think it would be easy to run into some subtle problems with an API such as .safeInnerHTML API, when mixed with .innerHTML. The approach where input is sanitized upon assignment (and the original is not stored anywhere) is possibly the best, but may still lead to trouble. One possibility is the behavior of innerHTML on or elements, which seems inconsistent and potentially dangerous across browsers; and in general, innerHTML manipulation following safeInnerHTML assignments seem like an easy way to accidentally mess things up on web application side. Deferred sanitization triggered by safeInnerHTML assignments is another possibility, but it creates a whole lot other issues, e.g.: foo.safeInnerHTML = '...' foo.innerHTML += 'Ta-dah!'; ...or: foo.safeInnerHTML = '...' bar.innerHTML = foo.safeInnerHTML; Tainting elements that had their contents accessed via .safeInnerHTML, and then tracking and propagating this data, is one way to avoid problems - but it introduces significant complexity and would be pretty opaque to developers; especially when dealing with .innerHTML on outer or nested elements. I think the syntax outlined in Adam's post is much safer, would definitely require far fewer implementation-level challenges, and would introduce fewer gotchas for web app developers by tying sanitization to a well-defined output container, rather than one of several content access methods. More importantly, it is also easily extensible to a solution that could be utilized by non-JS pages, as its logical 1:1 equivalent would be a nonced, locked element, say: ...unsanitized user content... This is not a fortunate syntax, but illustrates the idea reasonably well. The boundaries are guarded, so the approach is safe as long as the server can produce decent random boundaries, and the benefit is that server-generated pages can benefit from lightweight sanitization without the need to do all content rendering dynamically with client-side JS - which would make a huge difference. /mz ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Tue, Nov 24, 2009 at 11:21 PM, Maciej Stachowiak wrote: > If we tie it to an element or attribute, people may be tempted to just do it > in markup, which would be insecure. Maybe we should have a DOM API called webkitJailChildren("no-script-for-you") on Node that prevents future children from running script. Making it a DOM API prevents authors from trying to turn the feature on with markup. On Tue, Nov 24, 2009 at 11:27 PM, Michal Zalewski wrote: > > ...unsanitized user content... > I'd rather not go this route in our initial implementation. I think we should target the use case of a web site receiving an untrusted string via cross-origin XMLHttpRequest or postMessage. Adam ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 24, 2009, at 10:37 PM, Adam Barth wrote: On Tue, Nov 24, 2009 at 8:39 PM, Maciej Stachowiak wrote: On Nov 24, 2009, at 7:14 PM, Adam Barth wrote: In the below message to the WHATWG, Ian suggests that vendors experiment with an API that makes it easier for web developers to programmatically add static HTML content to their pages without XSSing themselves: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-June/020191.html I think we should do as he recommends. If no one objects, I'll add this to my list of things to work on. I think innerStaticHTML is a good idea. Is there also a use case for the "static" equivalent of insertAdjacentHTML()? I think we should experiment with the minimal API that seems useful. If the experiment is a success, we can scale it up. Michal suggested to me off-list and another possibility is to have an API that works like this: var jail = document.createElement("jail"); document.getElementById("foo"); jail.innerHTML = untrusted_string; We could do something similar with attributes: var jail = document.getElementById("foo"); jail.setAttribute("sandbox", "yes-please"); jail.innerHTML = untrusted_string; One of the nice things about using a DOM API is we don't have to worry about crazy parsing issues. If we tie it to an element or attribute, people may be tempted to just do it in markup, which would be insecure. Regards, Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Tue, Nov 24, 2009 at 8:39 PM, Maciej Stachowiak wrote: > On Nov 24, 2009, at 7:14 PM, Adam Barth wrote: >> In the below message to the WHATWG, Ian suggests that vendors >> experiment with an API that makes it easier for web developers to >> programmatically add static HTML content to their pages without XSSing >> themselves: >> >> http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-June/020191.html >> >> I think we should do as he recommends. If no one objects, I'll add >> this to my list of things to work on. > > I think innerStaticHTML is a good idea. Is there also a use case for the > "static" equivalent of insertAdjacentHTML()? I think we should experiment with the minimal API that seems useful. If the experiment is a success, we can scale it up. Michal suggested to me off-list and another possibility is to have an API that works like this: var jail = document.createElement("jail"); document.getElementById("foo"); jail.innerHTML = untrusted_string; We could do something similar with attributes: var jail = document.getElementById("foo"); jail.setAttribute("sandbox", "yes-please"); jail.innerHTML = untrusted_string; One of the nice things about using a DOM API is we don't have to worry about crazy parsing issues. Adam ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
Re: [webkit-dev] innerStaticHTML
On Nov 24, 2009, at 7:14 PM, Adam Barth wrote: In the below message to the WHATWG, Ian suggests that vendors experiment with an API that makes it easier for web developers to programmatically add static HTML content to their pages without XSSing themselves: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-June/020191.html I think we should do as he recommends. If no one objects, I'll add this to my list of things to work on. I think innerStaticHTML is a good idea. Is there also a use case for the "static" equivalent of insertAdjacentHTML()? - Maciej ___ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev