whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.13k stars 2.67k forks source link

Consider exposing some information about sandboxed origins. #3585

Open mikewest opened 6 years ago

mikewest commented 6 years ago

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

RByers commented 6 years ago

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

mozfreddyb commented 6 years ago

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

mikewest commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago
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