Re: [whatwg] postMessage: event.source allows navigation of sender
On Thu, 7 Feb 2008, Hallvord R M Steen wrote: Adam Barth and Collin Jackson pointed out to me that while investigating frame navigation policies they found that a recipient of a postMessage in Opera can set event.source.location, thus navigate the sender window/document. I think this is a bug in the API itself. This seems to violate the API's promise of safe cross-domain communication even with untrusted documents. One can imagine use cases where a script in document A has a reference to window B and thus can post messages, but window B does not have any to A and would not under normal circumstances be able to change A's address. I think this should be adressed by removing event.source entirely. It would be weird to disallow setting location on a window object in this context only. To allow posting replies we could instead define a function on the event object. Say for example document.addEventListener( 'message', function(e){ if(e.data=='Hi'){ e.reply('Hello'); } }, false ) As far as I know there are no non-symmetric Window visibility cases in HTML5. You can only postMessage() to a Window if the Window can see you. Is that not true? Anyway, getting a hold of a Window and setting its window.location.href are two different things, as noted below. The idea is that message channels are the solution around this, by the way -- you sent a port to a window you have access to (and that has access to you) and if it passes it on to a window you _don't_ have access to, it can't navigate you. On Thu, 7 Feb 2008, Thomas Broyer wrote: Shouldn't event.source.location be read-only? Isn't that a direct application of the same-origin policy? Yes and no -- location.href only allows navigation if a separate access check passes (not the same-origin check). Adam explains it well: On Thu, 7 Feb 2008, Adam Barth wrote: When one frame posts a message to another frame, the recipient frame obtains a pointer to the sender frame as the source attribute of the message event. In Opera, this leaks the capability to navigate the sender's frame to the recipient because Opera assumes that if a script has a JavaScript pointer to a frame then that script is permitted to navigate that frame. The source attribute of the message event does not leak any privileges to the recipient in Internet Explorer, Firefox, and Safari because these browsers do not make this assumption and instead check whether the script is permitted to navigate the frame when the script assigns window.location. In Opera, it is difficult to obtain a JavaScript pointer to a frame because Opera prevents scripts from reading window.frames[i] across domains. Internet Explorer, Firefox, and Safari all allow scripts to read window.frames[i] across domains. [...] Another way to resolve the issue is for Opera to match the other browsers and check whether a script is permitted to navigate a frame when that scripts assigns the frame's location. Right. This is defined here: http://www.whatwg.org/specs/web-apps/current-work/#security6 http://www.whatwg.org/specs/web-apps/current-work/#allowed On Thu, 7 Feb 2008, Hallvord R M Steen wrote: Implementing the ancestore policy takes care of most of the scenarios I can think of where you may want to post messages to a window that should not be allowed to change your location. One case I'm still somewhat concerned about is that one is allowed to set the location of any top-level window according to the ancestor policy, so calling postMessage on untrusted windows from your top window is still somewhat dangerous. That's something we have to allow for web compatibility and for this reason I still think removing event.source from the message event interface would be a good idea. We can't remove window.source, that's how you talk back. :-) For example, consider w=window.open(); w.opener = null; w.location = 'http://untrusted.example.org' w.postMessage( '...' ); Untrusted content now gets a window reference it would not otherwise have, and will be allowed to set location if this scripts runs in the top context of the opener. If the top-level location changes, the location bar will change too, and after that the pages can't communication usefully (all you can do is a phishing attack, but then the evil page could just as easily just open a new window and hope the user doesn't realise there are two windows open, it would have the same effect -- or just redirect its own window to the phishing window, or whatever). If this is really a concern, then use the iframe sandbox option. The sandboxed navigation browsing context flag will then take care of preventing any undue navigation. On Sat, 9 Feb 2008, Adam Barth wrote: One possibility is to prevent one frame from navigating another if the frames are in different units of related browsing contexts. This is consistent with HTML5's
Re: [whatwg] postMessage: event.source allows navigation of sender
On Feb 7, 2008 4:32 AM, Hallvord R M Steen [EMAIL PROTECTED] wrote: One case I'm still somewhat concerned about is that one is allowed to set the location of any top-level window according to the ancestor policy, Yes. I think there is a lot of room for improvement in this part of the navigation policy. The idea behind permitting the navigation of top-level windows is that browsers display the location of these windows in the location bar, but a user might not notice that the location bar has changed if the top-level window is navigated at an unexpected time. Firefox's implementation of the ancestor policy restricts the navigation of top-level windows based on openers (but only when navigating by name). As you know, Opera restricts the navigation of top-level windows based on a number of factors, including whether the window is displaying an HTTPS page and the destination of the navigation. For example, consider w=window.open(); w.opener = null; w.location = 'http://untrusted.example.org' w.postMessage( '...' ); Untrusted content now gets a window reference it would not otherwise have, and will be allowed to set location if this scripts runs in the top context of the opener. This is an interesting case because some web sites, for example Gmail, attempt to restrict which sites can navigate their frames by nulling the window.opener property of windows they creates. This technique is only partially effective because 1) Safari restores the opener property after navigation, http://bugs.webkit.org/show_bug.cgi?id=17111. 2) Gmail, in particular, doesn't clear the window.name property of its window. That means a malicious web site can navigate the Gmail window if it happens to have a name. It seems like a better solution is to improve the navigation policy for top-level windows. That way, web sites don't have to fight the losing battle of controlling references to their windows. One possibility is to prevent one frame from navigating another if the frames are in different units of related browsing contexts. This is consistent with HTML5's philosophy that different units of related browsing contexts could be run in different threads and do not interact directly. That way, if a user visits a web site by first creating a new tab, the existing frames cannot navigate the new site's frame. In addition, we could define a new target, for example _unrelated, such that calling window.open(url, _unrelated) would open the URL in a new unit of related browsing contexts. Under the proposed policy, the newly opened window would be unable to navigate its opener. (Of course, window.open would need to return null and the newly opened window's window.opener property would need to be null.) This would be a useful mechanism for applications like webmail that wish to open windows but do not wish to be associated with the content they open. Adam
Re: [whatwg] postMessage: event.source allows navigation of sender
I'm a bit late to this party due to turning off list email because I didn't think I could handle it in addition to all the other email I receive. I just reenabled it to not miss anything; we'll see how this actually goes this time around. :-\ Adam Barth wrote: On Feb 7, 2008 4:32 AM, Hallvord R M Steen [EMAIL PROTECTED] wrote: One case I'm still somewhat concerned about is that one is allowed to set the location of any top-level window according to the ancestor policy, Yes. I think there is a lot of room for improvement in this part of the navigation policy. While to an extent it seems there's agreement that the ancestor policy works well enough to not worry overly much about postMessage exposing the sender's window, the top-level window thing is a pretty big hole that breaks dumping content in an iframe if that content can't be trusted. postMessage exposing the sender isn't that meaningful if you can just change the toplevel site, even if the location bar changes correspondingly. (Really, who looks at the location bar on even dynamic, JSy pages other than after an intentional navigation? I doubt I do.) That said, I think a reply() method might be a better idea than a source property. I'm not sure how meaningful that would be for MessageEvent generically, but I guess source had that problem already for server-sent events. Do note it's more spec burden due to determining sender identity (could be mitigated by equating reply with calling postMessage on the proposed-hidden source property); dynamic scope-dependent behavior is no fun that way. It seems like a better solution is to improve the navigation policy for top-level windows. That way, web sites don't have to fight the losing battle of controlling references to their windows. Agreed. One possibility is to prevent one frame from navigating another if the frames are in different units of related browsing contexts. This doesn't help the iframe case, which is something that, say, Facebook or any site that embeds Google Maps would care about -- or, indeed, any site that wanted to display some other site in an iframe. The subsequent _unrelated proposal would need an extension for frames/iframes for this to be a complete solution. Jeff
Re: [whatwg] postMessage: event.source allows navigation of sender
On Feb 7, 2008 10:24 AM, Hallvord R M Steen wrote: Adam Barth and Collin Jackson pointed out to me that while investigating frame navigation policies they found that a recipient of a postMessage in Opera can set event.source.location, thus navigate the sender window/document. I think this is a bug in the API itself. If what you say is true (see below) I'd rather say it's a bug in Opera's implementation. This seems to violate the API's promise of safe cross-domain communication even with untrusted documents. One can imagine use cases where a script in document A has a reference to window B and thus can post messages, but window B does not have any to A and would not under normal circumstances be able to change A's address. Shouldn't event.source.location be read-only? Isn't that a direct application of the same-origin policy? The current draft contains the following note: Implementors are urged to take extra care in the implementation of this feature. It allows authors to transmit information from one domain to another domain, which is normally disallowed for security reasons. It also requires that UAs be careful to allow access to certain properties but not others. See also http://www.whatwg.org/specs/web-apps/current-work/multipage/section-history.html#security5 And setting the event.source (Window object)'s location property is covered by the following paragraph: In the ECMAScript DOM binding, the location members of the HTMLDocument and Window interfaces behave as if they had a setter: user agents must treats attempts to set these location attribute as attempts at setting the href attribute of the relevant Location object instead. — source: http://www.whatwg.org/specs/web-apps/current-work/multipage/section-history.html#location0 which invokes the #security5 above. -- Thomas Broyer
Re: [whatwg] postMessage: event.source allows navigation of sender
Hallvord, On Feb 7, 2008 1:24 AM, Hallvord R M Steen [EMAIL PROTECTED] wrote: Adam Barth and Collin Jackson pointed out to me that while investigating frame navigation policies they found that a recipient of a postMessage in Opera can set event.source.location, thus navigate the sender window/document. I think this is a bug in the API itself. When one frame posts a message to another frame, the recipient frame obtains a pointer to the sender frame as the source attribute of the message event. In Opera, this leaks the capability to navigate the sender's frame to the recipient because Opera assumes that if a script has a JavaScript pointer to a frame then that script is permitted to navigate that frame. The source attribute of the message event does not leak any privileges to the recipient in Internet Explorer, Firefox, and Safari because these browsers do not make this assumption and instead check whether the script is permitted to navigate the frame when the script assigns window.location. In Opera, it is difficult to obtain a JavaScript pointer to a frame because Opera prevents scripts from reading window.frames[i] across domains. Internet Explorer, Firefox, and Safari all allow scripts to read window.frames[i] across domains. This seems to violate the API's promise of safe cross-domain communication even with untrusted documents. One can imagine use cases where a script in document A has a reference to window B and thus can post messages, but window B does not have any to A and would not under normal circumstances be able to change A's address. Other browsers do not equate having a JavaScript pointer to a frame with the ability to navigate that frame. I think this should be adressed by removing event.source entirely. Another way to resolve the issue is for Opera to match the other browsers and check whether a script is permitted to navigate a frame when that scripts assigns the frame's location. On Feb 7, 2008 1:45 AM, Thomas Broyer [EMAIL PROTECTED] wrote: Shouldn't event.source.location be read-only? Isn't that a direct application of the same-origin policy? Internet Explorer, Firefox, Safari, and Opera all permit a script to write window.location across domains. This action is interpreted as a request to navigate the frame. The browser's frame navigation policy determines whether this navigation is permitted. Adam
Re: [whatwg] postMessage: event.source allows navigation of sender
On 07/02/2008, Hallvord R M Steen [EMAIL PROTECTED] wrote: That is of course a possibility. I don't have Firefox 3 handy so I'd appreciate somebody explaining how it is implemented there. By the way, I recommend Minefield (the Firefox 3 nightlies) to anyone. I now use it as my default browser on Windows. There are occasional bad builds, but mostly it's just better in every way than Firefox 2. Lots of nice incremental improvements to the interface, less memory-hogging, more responsive, better at handling 200 tabs open, and so on. The only minus point is that most of my favourite extensions haven't been updated yet. - d.
Re: [whatwg] postMessage: event.source allows navigation of sender
On 07/02/2008, Thomas Broyer [EMAIL PROTECTED] wrote: On Feb 7, 2008 10:24 AM, Hallvord R M Steen wrote: Adam Barth and Collin Jackson pointed out to me that while investigating frame navigation policies they found that a recipient of a postMessage in Opera can set event.source.location, thus navigate the sender window/document. I think this is a bug in the API itself. If what you say is true (see below) I'd rather say it's a bug in Opera's implementation. That is of course a possibility. I don't have Firefox 3 handy so I'd appreciate somebody explaining how it is implemented there. Shouldn't event.source.location be read-only? Isn't that a direct application of the same-origin policy? No, all user agents I know allow you to set window.location across domains. Not doing so would break literally millions of web pages. As event.source just points to the sending window object setting event.source.location is same as setting window.location . The current draft contains the following note: Implementors are urged to take extra care in the implementation of this feature. It allows authors to transmit information from one domain to another domain, which is normally disallowed for security reasons. It also requires that UAs be careful to allow access to certain properties but not others. Do you really thing this vague paragraph *can* be interpreted as saying normal same-domain policies should be extended with a stricter policy that also disallows setting location? It's not exactly clear. See also http://www.whatwg.org/specs/web-apps/current-work/multipage/section-history.html#security5 And setting the event.source (Window object)'s location property is covered by the following paragraph: In the ECMAScript DOM binding, the location members of the HTMLDocument and Window interfaces behave as if they had a setter: user agents must treats attempts to set these location attribute as attempts at setting the href attribute of the relevant Location object instead. Indeed. All UAs already do that - if you set location, you set .href. Have a look at section 4.7.4.1. Security which reads: User agents must raise a security exception whenever any of the members of a Location object are accessed by scripts whose origin is not the same as the Location object's associated Document's origin, with the following exceptions: * The href setter So setting location actually sets href, and setting href is explicitly permitted across domains. By my reading the spec clearly dictates what Opera has implemented, so the original question remains. -- Hallvord R. M. Steen
Re: [whatwg] postMessage: event.source allows navigation of sender
Adam Barth and Collin Jackson pointed out to me that while investigating frame navigation policies they found that a recipient of a postMessage in Opera can set event.source.location, thus navigate the sender window/document. I think this is a bug in the API itself. When one frame posts a message to another frame, the recipient frame obtains a pointer to the sender frame as the source attribute of the message event. In Opera, this leaks the capability to navigate the sender's frame to the recipient because Opera assumes that if a script has a JavaScript pointer to a frame then that script is permitted to navigate that frame. This is actually per the spec and required for web compatibility: any script that has a pointer to a window object can usually set its location property. I expect most UAs only disallow it for http-https communication and I know Opera is a tad stricter than the others and disallow it if domains do not match for https-https communication. If you have test cases that show other browsers disallowing scripts that have a pointer to a window object from setting location across domains I'd very much like to see them. Being more restrictive in certain cases would be nice but is in my experience not possible without too much breakage, so I'm very interested if you can demonstrate stricter policies that actually work. (Note that I am talking only about setting window.location here, not about e.g. targetting a named window with a window.open call - that's a different scenario entirely.) The source attribute of the message event does not leak any privileges to the recipient in Internet Explorer, Firefox, and Safari because these browsers do not make this assumption and instead check whether the script is permitted to navigate the frame when the script assigns window.location. Adam, I don't quite follow you here because I don't know any IE or Safari implementation of window.postMessage. I'm quite sure IE doesn't implement it, I tried googling for Safari and postMessage/cross-document messaging but didn't find anything. As far as I know only Firefox 3 betas and Opera supports this, so no other implementations can be tested. In Opera, it is difficult to obtain a JavaScript pointer to a frame because Opera prevents scripts from reading window.frames[i] across domains. Internet Explorer, Firefox, and Safari all allow scripts to read window.frames[i] across domains. We should probably fix that if there is consensus on the more liberal approach - though note that Opera nevertheless allows you to set window.frames[i].location across domain. I don't know how you tested allow scripts to read window.frames[i] to reach the above statement. If you try a simple alert(window.frames[i]) you're actually calling the toString() method of the window object, which Opera disallows across domains so you get a security exception there. (Perhaps a pointless one..) Other browsers do not equate having a JavaScript pointer to a frame with the ability to navigate that frame. Again if you can back that up with test cases I'd love to see them :-) I think this should be adressed by removing event.source entirely. Another way to resolve the issue is for Opera to match the other browsers and check whether a script is permitted to navigate a frame when that scripts assigns the frame's location. But this would have to be applied only when window.location was set in a message event handler - that would get very messy! Alternatively we could pass in a fake window object that does not allow setting location, but that would directly contradict the spec and not be much cleaner. A postback function on the event object is by far the cleanest approach I can think of. (Apologies to the Opera and Firefox developers who would have to change their implementations..) On Feb 7, 2008 1:45 AM, Thomas Broyer [EMAIL PROTECTED] wrote: Shouldn't event.source.location be read-only? Isn't that a direct application of the same-origin policy? Internet Explorer, Firefox, Safari, and Opera all permit a script to write window.location across domains. This action is interpreted as a request to navigate the frame. The browser's frame navigation policy determines whether this navigation is permitted. Exactly. -- Hallvord R. M. Steen
Re: [whatwg] postMessage: event.source allows navigation of sender
On Feb 7, 2008 2:27 AM, Hallvord R M Steen [EMAIL PROTECTED] wrote: Opera assumes that if a script has a JavaScript pointer to a frame then that script is permitted to navigate that frame. This is actually per the spec and required for web compatibility: any script that has a pointer to a window object can usually set its location property. This does not seem to be required for web compatibility because Internet Explorer, Firefox, and Safari all restrict what happens when you assign a frame's location property according to their navigation policy. If the navigation is denied, Internet Explorer opens the page in a popup instead (unless blocked by the popup blocker) and Firefox throws an exception. The latest nightly build of Safari also opens a popup window when a navigation is denied, but the currently deployed version only logs the error to the debug console. I expect most UAs only disallow it for http-https communication and I know Opera is a tad stricter than the others and disallow it if domains do not match for https-https communication. The frame navigation policy in Internet Explorer, Firefox, and Safari is based on origins. If two frames are in a different origin, the frame navigation policy does not distinguish origin differences due to hosts from origin differences due to schemes. If you have test cases that show other browsers disallowing scripts that have a pointer to a window object from setting location across domains I'd very much like to see them. Here is a test case: http://crypto.stanford.edu/~abarth/research/html5/sibling/ The first child frame is in a different origin from the top-level frame and from the second child frame. In Internet Explorer, Firefox, and Safari, the first frame can obtain a JavaScript pointer to the second frame, but cannot navigate the frame by assigning its location property. This demo works in Internet Explorer 7, Safari 3, and Firefox 3. Being more restrictive in certain cases would be nice but is in my experience not possible without too much breakage, so I'm very interested if you can demonstrate stricter policies that actually work. This demonstration shows that Internet Explorer, Firefox, and Safari restrict these cases. These browsers are widely deployed, and the best thing for compatibility would be for all browsers to consistently apply the same policy. (Note that I am talking only about setting window.location here, not about e.g. targetting a named window with a window.open call - that's a different scenario entirely.) Yes. Named window navigation is another scenario. Adam, I don't quite follow you here because I don't know any IE or Safari implementation of window.postMessage. I'm quite sure IE doesn't implement it, I tried googling for Safari and postMessage/cross-document messaging but didn't find anything. As far as I know only Firefox 3 betas and Opera supports this, so no other implementations can be tested. postMessage is implemented in the trunk version of Safari. http://nightly.webkit.org/ I do not know if postMessage will be implemented in Internet Explorer 8, but if it were to be implemented in IE8, the source attribute would not leak any privileges to the recipient because IE checks whether the navigation is permissible before performing the navigation. We should probably fix that if there is consensus on the more liberal approach Yes, interoperability would be improved if all browsers implemented the same security policy. though note that Opera nevertheless allows you to set window.frames[i].location across domain. I don't know how you tested allow scripts to read window.frames[i] to reach the above statement. If you try a simple The same demo at http://crypto.stanford.edu/~abarth/research/html5/sibling/ shows that Opera does not permit a script to assign top.frames[1].location when top and the second frame are in a different domain. Other browsers do not equate having a JavaScript pointer to a frame with the ability to navigate that frame. Again if you can back that up with test cases I'd love to see them :-) This is the same test case. I think this should be adressed by removing event.source entirely. Another way to resolve the issue is for Opera to match the other browsers and check whether a script is permitted to navigate a frame when that scripts assigns the frame's location. But this would have to be applied only when window.location was set in a message event handler - that would get very messy! I'm suggesting Opera should match the behavior of other browsers and check whether a navigation is permissible under its frame navigation policy before performing the navigation, regardless of how the browser was requested to perform the navigation. It is difficult to control navigation by containing references to frames because it is easy for JavaScript pointers to frames to escape in unexpected ways, for example via the source attribute of the message
Re: [whatwg] postMessage: event.source allows navigation of sender
On Feb 7, 2008, at 2:27 AM, Hallvord R M Steen wrote: The source attribute of the message event does not leak any privileges to the recipient in Internet Explorer, Firefox, and Safari because these browsers do not make this assumption and instead check whether the script is permitted to navigate the frame when the script assigns window.location. Adam, I don't quite follow you here because I don't know any IE or Safari implementation of window.postMessage. I'm quite sure IE doesn't implement it, I tried googling for Safari and postMessage/cross-document messaging but didn't find anything. As far as I know only Firefox 3 betas and Opera supports this, so no other implementations can be tested. The current development version of WebKit includes support for cross- document messaging. I don't think any publicly available version of IE has it. However I think Adam was speaking in the general sense here, that getting a window object reference that you couldn't otherwise would not leak navigation capability in the named browsers regardless of how you get it. Other browsers do not equate having a JavaScript pointer to a frame with the ability to navigate that frame. Again if you can back that up with test cases I'd love to see them :-) I don't have a test case handy for this but I can assure you Safari/ WebKit only allows navigating other frames in the following cases: // The navigation change is safe if the active frame is: // - in the same security origin as the target or one of the target's ancestors // Or the target frame is: // - a top-level frame in the frame hierarchy This test is applied at the time window.location is assigned. If these conditions are not met, assigning the location property of another frame/window has no effect. You can probably figure out how to make a test case based on this. Regards, Maciej
Re: [whatwg] postMessage: event.source allows navigation of sender
Opera assumes that if a script has a JavaScript pointer to a frame then that script is permitted to navigate that frame. This is actually per the spec and required for web compatibility Here is a test case: http://crypto.stanford.edu/~abarth/research/html5/sibling/ Ah sorry, I see what you mean. Haven't let all the implications of your ancestor policy research sink in yet. You are perfectly right that Opera's security policy here relies on disallowing getting the window object rather than setting location. Implementing the ancestore policy takes care of most of the scenarios I can think of where you may want to post messages to a window that should not be allowed to change your location. One case I'm still somewhat concerned about is that one is allowed to set the location of any top-level window according to the ancestor policy, so calling postMessage on untrusted windows from your top window is still somewhat dangerous. That's something we have to allow for web compatibility and for this reason I still think removing event.source from the message event interface would be a good idea. For example, consider w=window.open(); w.opener = null; w.location = 'http://untrusted.example.org' w.postMessage( '...' ); Untrusted content now gets a window reference it would not otherwise have, and will be allowed to set location if this scripts runs in the top context of the opener. -- Hallvord R. M. Steen
Re: [whatwg] postMessage: event.source allows navigation of sender
On Feb 7, 2008 10:59 AM, Hallvord R M Steen wrote: Have a look at section 4.7.4.1. Security which reads: User agents must raise a security exception whenever any of the members of a Location object are accessed by scripts whose origin is not the same as the Location object's associated Document's origin, with the following exceptions: * The href setter Oops! My bad, missed the exceptions... -- Thomas Broyer