- From: Ian Hickson <ian@hixie.ch>
- Date: Tue, 29 Jul 2008 22:48:29 +0000 (UTC)
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 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. This is already the case, since there's no way to get a hold of a Window object from another unit. > 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. <a href="..." rel="noreferrer"> basically does this per spec today. I don't want to do it for window.open() because window.open() in legacy UAs always returns a Window object, which would defeat the point. On Sat, 9 Feb 2008, Jeff Walden wrote: > > 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.) The point is that you can't distinguish changing a top-level frame from just opening a brand new top-level frame, so it's not really gaining you anything. The "sandbox" feature of <iframe> in HTML5 deals with this. > 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. I'm a little concerned about adding methods to the Event object, there isn't any precedent for that really. I'm also not convinced the attack scenario is really a problem. -- Ian Hickson U+1047E )\._.,--....,'``. fL http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Received on Tuesday, 29 July 2008 15:48:29 UTC