Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider exposing some information about sandboxed origins. #3585

Open
mikewest opened this issue Mar 22, 2018 · 11 comments
Open

Consider exposing some information about sandboxed origins. #3585

mikewest opened this issue Mar 22, 2018 · 11 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest security/privacy There are security or privacy implications topic: origin

Comments

@mikewest
Copy link
Member

Opaque origins serialize to "null". This means that CORS-enabled requests from <iframe sandbox> documents send an "Origin: null" header, and postMessage calls send an "{ ..., origin: "null", ... }" property in their payload. I've heard feedback from some folks internally at Google that this makes it difficult to harden some endpoints which use sandboxing to reduce the privilege of some piece of an application, as their sandboxed code is indistinguishable from anyone else's sandboxed code: both show up as "null".

It might be reasonable to expose some additional information about the sandboxed frame in these contexts. The origin of the frame's URL, for instance, would cover the cases I know of that folks cared about (though it would not cover srcdoc or data: constructs: if we wish to care about those, we'd need to find some way of defining what the origin would have been if the sandboxing flag wasn't present).

If including this additional information is reasonable, I have two suggestions:

  1. Change the serialization from "null" to something to something that embedded the data in a new format: for example "[https://example.com]" (With the square-brackets Which make a box. Because it's sandboxed. Get it? Totally clever, right?). The string-equality checks folks anecdotally do today would fail closed (probably), and folks who wanted to use sandboxes would be able to do so in a more granular fashion.

  2. Add additional metadata. That is, we'd continue sending an Origin: null header, and would tack on something like What-The-Origin-Header-Would-Have-Been-If-The-Initiator-Was-Not-Sandboxed: http://example.com (and likewise in the postMessage payload).

This seems like a problem worth solving, as encouraging folks to drop privileges in frames (especially third-party frames) can be valuable. I'm partial to 1) above, but only because I find the boxy-brackets unbearably clever. I'm very open to other suggestions.

WDYT?

/cc @RByers, @ojanvafai, @whatwg/security

@mikewest mikewest added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest security/privacy There are security or privacy implications topic: origin labels Mar 22, 2018
@RByers
Copy link

RByers commented Mar 22, 2018

Sounds great to me! I also have a slight preference for 1.

@mozfreddyb
Copy link
Contributor

Not sure I understand the original request.
If you want distinct origins with a specific name, don't you want suborigins?

@mikewest
Copy link
Member Author

If you want distinct origins with a specific name, don't you want suborigins?

That might be a way of doing things! In the future! When suborigins are defined and shipped anywhere at all!

Today, we can push documents into opaque origins via Content-Security-Policy: sandbox and <iframe sandbox="[flags go here]">. Applications do so now in order to separate privileges between code they trust and code they don't. Those applications can't reliably distinguish between their sandboxed frames/windows, and anyone else's sandboxed frames/windows. That is, <iframe sandbox="allow-scripts" src="https://example.com/"> and <iframe sandbox="allow-scripts" src="https://evil.com/"> both generate requests with an Origin header of null, which makes it difficult to distinguish them server-side.

Does that clarify the suggestion, @mozfreddyb?

@mozfreddyb
Copy link
Contributor

Oh, I understand that it's problematic not being able to distinguish between two null origins.
(I think @albinowax mentioned lots of bugs due to this in his AppSec EU presentation last year)

I'm just having a hard time accepting your proposed solution ;).
With 1) I'm afraid we might break null checks in existing code.
With 2) I wonder if we need to do that through an opt-in from the sender. Given that sending it implicitly somehow breaks the Same Origin Policy?

@johnwilander
Copy link

Are there cases where the embedder wants to restrict the sandboxed embeddee’s ability to make CORS requests and send postMessages with its real origin? I would guess so. The allow-same-origin token seems to touch on this issue.

@mozfreddyb
Copy link
Contributor

Ah. Nevermind about 2). if it does postMessage, then it will already tell it's origin openly. No point in being concerned about it leaking for the sandboxedcase.

@mikewest
Copy link
Member Author

Thanks for your feedback, @mozfreddyb and @johnwilander!

With 1) I'm afraid we might break null checks in existing code.

Yup. I've done no actual research, just skimmed through a few onmessage handlers in Google's code. The ones that I saw would fail closed, which is the right answer from a security perspective; of course, we'd need to do actual research to see if it's web compatible with regard to user-visible impact.

With 2) I wonder if we need to do that through an opt-in from the sender. Given that sending it implicitly somehow breaks the Same Origin Policy?

Depending on how exacting you are, the Origin header already violates the SOP. It's not clear that exposing the origin of the URL of a sandboxed document does any damage beyond the status quo.

Are there cases where the embedder wants to restrict the sandboxed embeddee’s ability to make CORS requests and send postMessages with its real origin? I would guess so. The allow-same-origin token seems to touch on this issue.

Could you give an example of sandbox usage that would have this kind of requirement? I ask because sandbox doesn't actually prevent making CORS-enabled requests today, it simply prevents the recipient from making an informed decision about whether or not to accept/act on the request. That is, a document inside <iframe sandbox="allow-scripts"> can make any fetch() calls it likes: complicated requests might cause a preflight or cause the Origin header to be sent. Today, it's sent as null, which is certainly opaque, but means that sandboxes are hard to use as privilege separation, as every sandbox, yours and mine, looks alike.

Assuming that we find such an example, I suppose an option would be to add a new sandbox flag, like allow-embedding-the-original-origin-before-sandboxing-in-this-frames-origin-serialization (or to do the same opt-in via Feature Policy). Would you be more comfortable with that approach?

@johnwilander
Copy link

Are there cases where the embedder wants to restrict the sandboxed embeddee’s ability to make CORS requests and send postMessages with its real origin? I would guess so. The allow-same-origin token seems to touch on this issue.

Could you give an example of sandbox usage that would have this kind of requirement? I ask because sandbox doesn't actually prevent making CORS-enabled requests today, it simply prevents the recipient from making an informed decision about whether or not to accept/act on the request. That is, a document inside <iframe sandbox="allow-scripts"> can make any fetch() calls it likes: complicated requests might cause a preflight or cause the Origin header to be sent. Today, it's sent as null, which is certainly opaque, but means that sandboxes are hard to use as privilege separation, as every sandbox, yours and mine, looks alike.

Assuming that we find such an example, I suppose an option would be to add a new sandbox flag, like allow-embedding-the-original-origin-before-sandboxing-in-this-frames-origin-serialization (or to do the same opt-in via Feature Policy). Would you be more comfortable with that approach?

What I mean is, the embedder restricts the embedee through sandboxing. The embedee not being able to talk to its server revealing its origin is such a restriction, i.e. sandboxed iframes in the null origin cannot communicate with their servers with the level of authentication that browser-guaranteed origin gives. If we change that by default, we weaken the sandbox.

@bzbarsky
Copy link
Contributor

I think it's worth taking a step back and asking what actual use cases sandbox is meant to support.

The initial goal was to allow hosting third-party-provided content on your own site with some semblance of safety, if I recall correctly. Though that's somewhat undermined by the possible ability to link directly to that content, so the "really safe" versions of that are srcdoc or blob:// URLs.... In practice, you end up having to put the third-party content on a different hostname and sandbox it; the latter to disallow things like it navigating your toplevel page and whatnot.

Is there a summary document somewhere of the use cases we are now trying to shoehorn into "sandbox"? Because the concept of "my sandboxed code" as presented in the first comment in this issue is complete nonsense in the original sandbox design: the whole point was that not-your-stuff would go in the sandbox. If we're going to be trying to completely redesign what the point of sandbox is, we really need clarity on what we're trying to accomplish.

On the specific proposal here, I'm somewhat opposed to changing the behavior of existing headers that people may be depending on for critical security guarantees. So if we do add something that exposes something I would like it to be additional metadata, probably. All of that may change depending on the outcome of the "what is the point of sandbox?" question.

@arturjanc
Copy link

arturjanc commented Mar 24, 2018

Is there a summary document somewhere of the use cases we are now trying to shoehorn into "sandbox"?

I don't think there exists a doc that directly answers your question, though many of the use cases from the Suborigins explainer apply here, and some could potentially be easier to achieve via a "better sandbox".

Specifically, developers seem to like the idea of limiting the capabilities of parts of their own application (see e.g. this upcoming talk by @devd; AFAIK this was also relatively well-received at TPAC modulo the implementation concerns of suborigins). Reducing the privileges of trusted-but-potentially-vulnerable pages seems like a useful mechanism to protect against XSS, and sandbox comes relatively close to allowing developers to do so. I believe Mike is interested in extending this to make implementing such separation easier for developers; allowing the sandboxed document to safely communicate with the parts of its origin which opt into such communication would help accomplish this.

Do you have any thoughts about extending the conceptual model of the sandbox to extend to this case?

@guest271314
Copy link
Contributor

At Chromium/Chrome you can utilize one or more values within window.location.ancestorOrigins array to provide some information about the origin of the message

    <script>
      let Origin;
      window.onmessage = e =>{
        if (!Origin) {
          Origin = e.data;
        }
        console.log(e, Origin);
      }
    </script>
    <iframe sandbox="allow-scripts" src="iframe.html"></iframe>

and use a query string parameters to avoid pre-flight requests

    <script>
      let [Origin] = window.location.ancestorOrigins;
      window.parent.postMessage({Origin}, Origin);
      let params = new URLSearchParams({Origin});
      let url = `/path/to/resource?${params.toString()}`;
      fetch(url);
    </script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest security/privacy There are security or privacy implications topic: origin
Development

No branches or pull requests

7 participants