[whatwg] postMessage: event.source allows navigation of sender
Ian Hickson
ian at hixie.ch
Tue Jul 29 15:48:29 PDT 2008
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. `._.-(,_..'--(,_..'`-.;.'
More information about the whatwg
mailing list