Script execution on detached frames

35 views
Skip to first unread message

Kentaro Hara

unread,
May 9, 2016, 4:59:50 AM5/9/16
to platform-architecture-dev, Jochen Eisinger, Daniel Cheng, Jens Widell
Hi

TL;DR: Help me understand the spec about how scripts should behave on detached frames :)

Background: Script execution on detached frames has caused a bunch of security issues. I'm now investigating if it's feasible to forbid script execution on detached frames.

Consider the following code:

<script>
onload = function() {
  var iframe = document.createElement("iframe");
  document.body.appendChild(iframe);
  var win = iframe.contentWindow;
  var doc = iframe.contentWindow.document;
  win.foo = "aaa";
  doc.foo = "bbb";
  document.body.removeChild(iframe);
  var iterator = doc.createNodeIterator(doc, NodeFilter.SHOW_ELEMENT, null, false);
  console.log(win.foo);
  console.log(doc.foo);
  console.log(iterator);
}
</script>

Chrome, Firefox, Safari and IE behave as follows:

Chrome:
aaa
bbb
[object NodeIterator]

Firefox:
aaa
undefined
[object NodeIterator]

Safari:
undefined
bbb
[object NodeIterator]

IE:
undefined
bbb
[object NodeIterator]

As far as I read the spec, it is saying that "User agents must not allow the user to interact with child browsing contexts of elements that are in Documents that are not themselves fully active". I interpret this meaning that user agents must not allow the user to interact with detached iframes. Thus I think the code should behave as follows:

undefined or throw an exception
undefined or throw an exception
undefined or throw an exception

Here are a couple of questions:

1) What does "user agents must not allow..." mean? Does it mean that window.foo should return undefined? Or does it mean that it should throw an exception?

2) If the user calls doc.createNodeIterator(), should we interpret that the user is interacting with the detached frame, or not? doc.createNodeIterator() is not explicitly touching the iframe's window object but is implicitly interacting with the iframe's window object by creating a DOM wrapper on the window object. In other words, should doc.createNodeIterator() return a valid DOM wrapper? Or should it return undefined or throw an exception? (As described above, all the browsers are returning a valid DOM wrapper currently.)

3) When is an unload handler dispatched? I think the unload handler should have an ability to do something on the detached frame. Is the unload handler dispatched before Frame::detach is called? Or is the unload handler dispatched after Frame::detach is called but before LocalDOMWindow::reset is called? (If the latter is the case, we need to somehow support executing the unload handler on the detached frame.)




--
Kentaro Hara, Tokyo, Japan

Jens Widell

unread,
May 9, 2016, 6:09:40 AM5/9/16
to Kentaro Hara, platform-architecture-dev, Jochen Eisinger, Daniel Cheng
On Mon, May 9, 2016 at 10:59 AM, Kentaro Hara <har...@chromium.org> wrote:
> Hi
>
> TL;DR: Help me understand the spec about how scripts should behave on
> detached frames :)
>
> Background: Script execution on detached frames has caused a bunch of
> security issues. I'm now investigating if it's feasible to forbid script
> execution on detached frames.

In the security issues (the ones I was involved with, at least) the
script that performed the "attack" was itself running in the detached
iframe.

In fact, it first navigated the iframe, and then detached it. So not
only was the browsing context detached, it had also been navigated to
a different security origin, and yet was executing a script from the
original origin.

Continuing to execute a script in this situation feels questionable to me.


Of limited relevance:

In Presto, which did not follow the relevant parts of HTML5 very well
at all, I think the navigation would be postponed until the script
that triggered it finished executing; and detaching the iframe would
abruptly kill the script. I suspect both of these behaviors caused
compatibility issues for us back then, but probably nothing major.

--
Jens

Yuki Shiino

unread,
May 9, 2016, 9:19:53 AM5/9/16
to Jens Widell, Kentaro Hara, platform-architecture-dev, Jochen Eisinger, Daniel Cheng
I think that we need to distinguish "child browsing contexts" from "nested browsing contexts".  And then, I think that "User agents must not allow the user to interact with child browsing contexts of ..." in the spec DOES NOT apply to the case of detached iframes, because the detached iframe's browsing context is NOT a child browsing context, though it's a nested browsing context.

I've not yet deeply dived into this problem, but my interpretation of "User agents must not allow ..." is that:
The user script is only allowed to access to the page currently shown.  It's not allowed to access to "previously shown pages".

A browser context has a session history.
There are multiple documents in the history.
The active document means, roughly speaking, the current page's document.

For child browsing contexts, since it's attached, it has a session history and multiple documents in it.  The user is only allowed to access to the active document (= the current page's document).  It's not allowed to access to any other documents in the history.

For nested browsing contexts that are not child browsing contexts, since it's not attached, there is no session history.  Then, there is no need to mention to "the active document".


Back to the original problem, I think there are several stages about iframes.
1) iframe is created but not yet attached.
2) iframe is attached.
3) iframe is detached.
4) iframe once attached and detached, and gets attached again.
If the user script is allowed to run at 1), then I don't see a reason why it's not allowed at 3).

My gut feeling (sorry being very vague) is that the user script is allowed to run at all the stages above.

Cheers,
Yuki Shiino


--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architect...@chromium.org.
To post to this group, send email to platform-arc...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CAEef6WzqLyprsh2M5dkA4e0MHiY6VT%2BwLw62Tc-Asjn0zSD7xg%40mail.gmail.com.

Domenic Denicola

unread,
May 9, 2016, 11:54:28 AM5/9/16
to Kentaro Hara, platform-architecture-dev, Jochen Eisinger, Daniel Cheng, Jens Widell
That sentence is talking about users, not authors (= web developers). So that sentence does not have any normative impact on the behavior of win.foo, doc.foo, or iterator.

It's basically saying "don't present some way for users to click on links or buttons in such iframes".

Per spec, I believe the answers should be aaa, bbb, [object NodeIterator]. (At least for same-origin iframes; I haven't checked the more complex cross-origin case.)
 

2) If the user calls doc.createNodeIterator(), should we interpret that the user is interacting with the detached frame, or not? doc.createNodeIterator() is not explicitly touching the iframe's window object but is implicitly interacting with the iframe's window object by creating a DOM wrapper on the window object. In other words, should doc.createNodeIterator() return a valid DOM wrapper? Or should it return undefined or throw an exception? (As described above, all the browsers are returning a valid DOM wrapper currently.)

3) When is an unload handler dispatched? I think the unload handler should have an ability to do something on the detached frame. Is the unload handler dispatched before Frame::detach is called? Or is the unload handler dispatched after Frame::detach is called but before LocalDOMWindow::reset is called? (If the latter is the case, we need to somehow support executing the unload handler on the detached frame.)




--
Kentaro Hara, Tokyo, Japan

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architect...@chromium.org.
To post to this group, send email to platform-arc...@chromium.org.

Elliott Sprehn

unread,
May 9, 2016, 1:39:57 PM5/9/16
to Domenic Denicola, Kentaro Hara, platform-architecture-dev, Jochen Eisinger, Daniel Cheng, Jens Widell
In either case without lots of checks in the bindings there's no way to disable all scripts that would connect back to the detached iframe.

ex.

IframeArray = iframe.contentWindow.Array;
iframe.remove()
var a = new IframeArray();
a.push(...);

so we could disable DOM objects, and we already disable all the ActiveDOMObjects in there I think (ex. setTimeout on the detached frame stops working), but we can't disable scripting in general.


Kentaro Hara

unread,
May 10, 2016, 5:37:41 AM5/10/16
to Elliott Sprehn, Domenic Denicola, platform-architecture-dev, Jochen Eisinger, Daniel Cheng, Jens Widell
Thanks all for comments -- I'm getting a better understanding.

Today I did further investigation on detached frames and got more confusing results. Let me study a bit more and try to come up with a proposal that will decrease a risk of running DOM operations on detached frames.




Reply all
Reply to author
Forward
0 new messages