Non-privileged iframe can unwrap privileged wrappers

RESOLVED INVALID

Status

()

RESOLVED INVALID
2 years ago
2 years ago

People

(Reporter: Oriol, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

2 years ago
1. Open a new tab

2. Open the web console. It will be privileged because it's a new tab

3. Enter this code:

    Components.utils.import('resource://gre/modules/jsdebugger.jsm');
    addDebuggerToGlobal(this);
    var iframe = document.createElement("iframe");
    document.documentElement.appendChild(iframe);

4. Enter this code:

    var dbg = new Debugger().addDebuggee(iframe.contentWindow);

5. Then the following code will return `null`, because it is not permitted to unwrap. I believe this is expected.

    dbg.makeDebuggeeValue([1,2,3]).unwrap();

6. Enter this code

    document.documentElement.appendChild(iframe);
    var dbg = new Debugger().addDebuggee(iframe.contentWindow);

7. Now you can unwrap properly

    dbg.makeDebuggeeValue([1,2,3]).unwrap();


I think this should not happen. It looks like some security restriction has been bypassed.
looks like it's related to when to add debuggee after appending iframe to tree.

A:
  Components.utils.import('resource://gre/modules/jsdebugger.jsm');
  addDebuggerToGlobal(this);
  var iframe = document.createElement("iframe");
  setTimeout(function() {
    document.documentElement.appendChild(iframe);
    var dbg = new Debugger().addDebuggee(iframe.contentWindow);
    console.log(dbg.makeDebuggeeValue([1,2,3]).unwrap() == null);
  }, 0);

B:
  Components.utils.import('resource://gre/modules/jsdebugger.jsm');
  addDebuggerToGlobal(this);
  var iframe = document.createElement("iframe");
  document.documentElement.appendChild(iframe);
  setTimeout(function() {
    var dbg = new Debugger().addDebuggee(iframe.contentWindow);
    console.log(dbg.makeDebuggeeValue([1,2,3]).unwrap() == null);
  }, 0);

A prints false, and B prints true.

Comment 2

2 years ago
This looks like it should be a sec bug. Bobby, can you take a look?
Group: core-security-release
Flags: needinfo?(bobbyholley)
I don't see any unexpected behavior here.

When you insert an iframe into the dom and synchronously access .contentWindow, you get a transient about:blank window whose principal is the same as the principal of the iframe (in this case, System Principal). Once we return to the event loop, the load replaces the contentWindow with the "loaded" window, which in this case is moz-safe-about:blank codebase principal (non-System).

So depending on the order of things, the window you're working with may or may not have the System Principal. The code is being evaluated in a System Principal scope. So if both are system, we won't get any permission errors. However, if the debuggee scope is _not_ system, then invoking makeDebuggeeValue with a system-side object will create a Debugger handle for a codebase->system wrapper, which denies access (because less-privileged code is trying to access more-privileged code). So unwrapping it fails, as we would expect.
Group: core-security-release
Status: NEW → RESOLVED
Last Resolved: 2 years ago
Flags: needinfo?(bobbyholley)
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.