Closed
Bug 1252751
Opened 8 years ago
Closed 8 years ago
<iframe sandbox srcdoc> can bypass mixed content restrictions
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla48
Tracking | Status | |
---|---|---|
firefox48 | --- | fixed |
People
(Reporter: pauljt, Assigned: baku)
References
Details
(Keywords: sec-moderate, Whiteboard: [adv-main48-] btpp-active)
Attachments
(4 files, 5 obsolete files)
946 bytes,
text/html
|
Details | |
1.36 KB,
text/html
|
Details | |
4.87 KB,
patch
|
Details | Diff | Splinter Review | |
4.23 KB,
patch
|
Details | Diff | Splinter Review |
Websockets initiated from pages secure origins (https) must also be secured by TLS (ie. they must have a scheme of wss:) This restriction can be bypassed by embedding an sandboxed iframe and setting the srcdoc of this iframe to load the websocket on the parent page's behalf. I'm not certain that this is actually a bug though. Is the origin of a sandboxed iframe considered different to the parent frame and therefore not be bound by the parent frame's restriction? Or should mixed content blocking take precedence and the insecure websocket connection should be blocked.
Reporter | ||
Comment 1•8 years ago
|
||
When loaded on a TLS enabled site, this page can connect to a websocket server on the local network in Firefox 44. FWIW its blocked with a mixed content error in Chrome 48.
Reporter | ||
Comment 2•8 years ago
|
||
Hmm bug 1204269 was rated as sec-moderate and it sounds like a similar thing. Not sure I agree with that rating, but perhaps I'm missing the risk here?
Reporter | ||
Comment 3•8 years ago
|
||
Same problem exists with XHR and sandbox iframe. XHR from https to http _should_ be blocked due to mixed content blocker, but iframe sandbox bypasses this restriction. Seems to be something with sandbox I tested with srcdoc, src=data:,foo and src=https://foo and all were able to make requests to http, even though the top level resource was https.
Comment 4•8 years ago
|
||
I think this is a real problem, and "sec-other" hides it. Clearing so we can make another triage pass at it.
Keywords: sec-other
Updated•8 years ago
|
Component: Networking: WebSockets → DOM
Summary: Websocket security restrictions can be bypassed with <iframe sandbox srcdoc> → <iframe sandbox srcdoc> can bypass mixed content restrictions
Reporter | ||
Comment 5•8 years ago
|
||
See also bug 1073952
Comment 7•8 years ago
|
||
Tanvi? Chris? Any ideas about how to fix this one?
Flags: needinfo?(tanvi)
Flags: needinfo?(sworkman)
Flags: needinfo?(mozilla)
Comment 8•8 years ago
|
||
I won't be able to look into this until the week after next. Chris, if you have time, please take a look. If it is a sec-low, it can wait.
Comment 9•8 years ago
|
||
I suspect someone from DOM needs to look at this, e.g., :baku or :smaug. It seems more likely that DOM doesn't pass the correct data to network than the other way around.
Comment 10•8 years ago
|
||
(In reply to Anne (:annevk) from comment #9) > I suspect someone from DOM needs to look at this, e.g., :baku or :smaug. It > seems more likely that DOM doesn't pass the correct data to network than the > other way around. The MixedContentBlocker implementation accepts TYPE_WEBSOCKET [1] because the WebSocket API should already block such loads [2]. Now, whether we should update the mixed content implementation to block such loads is debatable. Anyway, the true reason why we are not blocking the load happens within Websocket.cpp [2]. The problem is that the |originURI| is "moz-nullprincipal:{e217e9cd-2c29-4677-af3a-452178f6c56f}" when running the testcase provided in Comment 0, hence originisHttps is false and we don't bail out with an error here [3]. Baku, I suppose we should rather use the originDoc's URI in that case, right? [1] http://mxr.mozilla.org/mozilla-central/source/dom/security/nsMixedContentBlocker.cpp#462 [2] http://mxr.mozilla.org/mozilla-central/source/dom/base/WebSocket.cpp#1580 [3] http://mxr.mozilla.org/mozilla-central/source/dom/base/WebSocket.cpp#1608
Flags: needinfo?(mozilla) → needinfo?(amarchesini)
Comment 11•8 years ago
|
||
For the specific WebSocket issue, yes, we should move the mixed content blocking away from the API into the network layer. See https://w3c.github.io/webappsec-mixed-content/#websockets-integration for details. I plan to reconcile WebSocket and Fetch in https://github.com/whatwg/fetch/issues/235 so they will more clearly share the same processing model.
Assignee | ||
Updated•8 years ago
|
Assignee: nobody → amarchesini
Flags: needinfo?(amarchesini)
Assignee | ||
Updated•8 years ago
|
Flags: needinfo?(tanvi)
Comment 12•8 years ago
|
||
It is still not clear to me what the spec says about this case. "If secure is false but the origin specified by the entry settings object has a scheme component that is itself a secure protocol" sure, but what makes the sandboxed iframe to have "secure protocol"
Comment 13•8 years ago
|
||
...in case we're using srcdoc.
Comment 14•8 years ago
|
||
Olli, please read https://w3c.github.io/webappsec-mixed-content/#websockets-integration for the proper security check. The WebSocket API in HTML is a little unreliable at the moment. I'm fixing this with https://github.com/whatwg/fetch/pull/236 which rewrites part of the WebSocket protocol in terms of Fetch and then I'll create a separate PR against HTML which will make the WebSocket API hook into that. Then it should no longer have such naive Mixed Content checks.
Assignee | ||
Comment 15•8 years ago
|
||
Here a proposed fix: I get the principal from the parent window in case the current one is a null principal. Smaug also asked this question: "what leads the iframe to have secure protocol per spec?" but I still don't have a valid answer.
Attachment #8727809 -
Flags: review?(bugs)
Comment 16•8 years ago
|
||
Per https://w3c.github.io/webappsec-mixed-content/#categorize-settings-object mixed content uses "HTTPS state", not "secure protocol". As I said, what the HTML Standard says about the WebSocket API is wrong temporarily. I'm working on fixing it. (I think jwatt is implementing "HTTPS state" as part of secure contexts.)
Comment 17•8 years ago
|
||
Comment on attachment 8727809 [details] [diff] [review] ws2.patch What if an <iframe sandbox srcdoc> has another <iframe sandbox srcdoc> inside it? You need to iterate higher up in the browsing context tree. What if sandboxed iframe has 'allow-popups allow-scripts' and calls window.open("about:blank", ...) and then uses that window's WebSocket? Don't you need to check the opener and if opener is has also null principal, iterate higher up? (I didn't test this case)
Attachment #8727809 -
Flags: review?(bugs) → review-
Assignee | ||
Comment 18•8 years ago
|
||
Test included
Attachment #8727809 -
Attachment is obsolete: true
Attachment #8727877 -
Flags: review?(bugs)
Comment 19•8 years ago
|
||
Comment on attachment 8727877 [details] [diff] [review] ws2.patch So nothing guarantees we don't end up to endless loop here. Remember top level window's parent is the parent itself. window.open case is still unclear to me. Which principal do we end up passing there when about:blank is opened?
Attachment #8727877 -
Flags: review?(bugs) → review-
Comment 20•8 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #19) > Comment on attachment 8727877 [details] [diff] [review] > ws2.patch > > So nothing guarantees we don't end up to endless loop here. Remember > top level window's parent is the parent itself. Please note that all this docshell traversal logic is already happening within nsMixedContentBlocker. At the moment we bail out early for TYPE_WEBSOCKET within the mixed content implementation. Potentially the right fix is to update MixedContentBlocker instead of duplicating that logic within WebSocket.cpp.
Comment 21•8 years ago
|
||
Christoph, it sounds like that would be the right fix. Note that going forward we don't want to throw for this case in the WebSocket API. It needs to be identical to a network failure.
Comment 22•8 years ago
|
||
(In reply to Anne (:annevk) from comment #21) > Christoph, it sounds like that would be the right fix. > > Note that going forward we don't want to throw for this case in the > WebSocket API. It needs to be identical to a network failure. The only question I have is: The user is able to overwrite mixed content restrictions. I suppose that should also apply to the case described in this bug, right? In other words, if the user 'allows mixed content', then the insecure (ws://) websocket should load, right?
Comment 23•8 years ago
|
||
User should not be able to overwrite mixed content restriction, since the restriction is coming from the WebSocket API spec. (whether or not the limitation will be moved to some other spec doesn't really matter). And throwing the security exception there has been in the API for quite some time. Maybe. The spec situation is a bit too messy here when it comes to sandbox+srcdoc.
Comment 24•8 years ago
|
||
It's equivalent to allowing mixed content XMLHttpRequest. If they can do it for XMLHttpRequest, I guess it makes sense that we remain consistent. My personal view is that we should not offer this option to users to begin with. This is rare and users will only lose if they get tricked into doing it.
Comment 25•8 years ago
|
||
Perhaps I'm missing something here, but I don't see nsMixedContentBlocker to have code which could be reused here. It has code to check parent browsing contexts, but doesn't have anything to check opener.
Comment 26•8 years ago
|
||
FWIW, (3) in https://bugzilla.mozilla.org/show_bug.cgi?id=1220687#c19 would be really nice here, but we should probably fix this in branches too, so can't wait that bug to be fixed.
Comment 27•8 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #25) > Perhaps I'm missing something here, but I don't see nsMixedContentBlocker to > have code which could be reused here. It has code to check parent browsing > contexts, but doesn't have anything to check opener. Potentially you are right and I confused those concepts. I ran the test from this bug and realized that within mixedContentBlocker we got the right 'context', but you are right, that's the parent browsing context, not the opener.
Updated•8 years ago
|
Keywords: sec-moderate
Assignee | ||
Comment 28•8 years ago
|
||
Indeed we should move this check outside the WebSocket API. Maybe nsContentUtils waiting for something better.
Attachment #8727877 -
Attachment is obsolete: true
Attachment #8728318 -
Flags: review?(bugs)
Comment 29•8 years ago
|
||
Comment on attachment 8728318 [details] [diff] [review] ws2.patch >+ >+ nsCOMPtr<nsPIDOMWindowInner> innerWindow; >+ >+ while (true) { >+ bool isNullPrincipal = true; >+ if (principal) { >+ aRv = principal->GetIsNullPrincipal(&isNullPrincipal); >+ if (NS_WARN_IF(aRv.Failed())) { >+ return; >+ } So we end up throwing some random error to web js here. >+ } >+ >+ if (!isNullPrincipal) { >+ break; >+ } >+ >+ if (!innerWindow) { >+ innerWindow = mWebSocket->GetOwner(); >+ if (NS_WARN_IF(!innerWindow)) { So we shouldn't use owner here, but globalObject, defined above. The spec talks about entry settings object. >+ aRv.Throw(NS_ERROR_FAILURE); >+ return; >+ } and here NS_ERROR_FAILURE same also elsewhere. I think I'd prefer if we used NS_ERROR_DOM_SECURITY_ERR for these cases. >+ // We are at the top. Let's see if we have a opener window. s/a/an/ >+ nsCOMPtr<nsIDocument> document = innerWindow->GetDoc(); GetExtantDoc() I think I'd like to see another patch using entry global and not the owner. Sorry that I didn't catch that before.
Attachment #8728318 -
Flags: review?(bugs) → review-
Assignee | ||
Comment 30•8 years ago
|
||
Attachment #8728318 -
Attachment is obsolete: true
Attachment #8728607 -
Flags: review?(bugs)
Comment 31•8 years ago
|
||
Comment on attachment 8728607 [details] [diff] [review] ws2.patch >+} else if (location.search == '?timeout') { >+ setTimeout(function() { >+ try{ >+ var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic'); >+ socket.onerror = function(e) { >+ opener.postMessage('WS onerror', '*'); >+ }; >+ socket.onopen = function(event) { >+ opener.postMessage('WS onopen', '*'); >+ }; >+ } catch(e) { >+ if (e.name == 'SecurityError') { >+ opener.postMessage('WS Throws!', '*'); >+ } else { >+ opener.postMessage('WS Throws something else!', '*'); >+ } >+ } >+ }, 0); what is this timeout about? Please remove it. If it is needed, it hints we have a bug somewhere. Don't you need to close() the window you opened? Usually mochitest warns about unclosed tabs/windows. Fix those 2 cases and split the test to separate patch so that the actual patch can be landed before landing the tests.
Attachment #8728607 -
Flags: review?(bugs) → review+
Assignee | ||
Comment 32•8 years ago
|
||
> what is this timeout about? Please remove it. If it is needed, it hints we
> have a bug somewhere.
The timeout is used when '?popup' is used. In this case we create webSocket from a window.open() from a function scheduled by a setTimeout(..., 0);
Mochitest and open windows are OK. browser tests complain about it. But I'll push to try for a double confirm.
Assignee | ||
Comment 33•8 years ago
|
||
Assignee | ||
Comment 34•8 years ago
|
||
Attachment #8728607 -
Attachment is obsolete: true
Updated•8 years ago
|
Whiteboard: btpp-followup-2016-03-11 → btpp-active
Comment 35•8 years ago
|
||
(In reply to Andrea Marchesini (:baku) from comment #32) > > what is this timeout about? Please remove it. If it is needed, it hints we > > have a bug somewhere. > > The timeout is used when '?popup' is used. In this case we create webSocket > from a window.open() from a function scheduled by a setTimeout(..., 0); > > Mochitest and open windows are OK. browser tests complain about it. But I'll > push to try for a double confirm. What does the test complain? Creating websocket there should just work the same way as without timeout
Assignee | ||
Comment 36•8 years ago
|
||
Attachment #8729387 -
Attachment is obsolete: true
Comment 37•8 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/f30fc906416f
Status: NEW → RESOLVED
Closed: 8 years ago
status-firefox48:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla48
Comment 38•8 years ago
|
||
Back from PTO, so chiming in late here. The reason nsMixedContentBlocker bails out early for websockets is because the websocket code is supposed to ensure that mixed content websockets are not allowed (no ws on https) with no ability for user to override. If we'd like nsMixedContentBlocker to handle this logic instead, we could make that change. We would have to special case TYPE_WEBSOCKET to ensure that user overrides don't affect them.
Updated•8 years ago
|
Group: dom-core-security → core-security-release
Comment 39•8 years ago
|
||
Paul, would you be able to take a quick look at this bug make sure it's been fixed?
Flags: needinfo?(ptheriault)
Updated•8 years ago
|
Whiteboard: btpp-active → [adv-main48-] btpp-active
Updated•7 years ago
|
Group: core-security-release
Comment 40•7 years ago
|
||
Andrea, why did the tests here never land?
Comment 41•7 years ago
|
||
(I tried, they don't pass on trunk, FWIW.)
Assignee | ||
Comment 42•7 years ago
|
||
(In reply to :Ehsan Akhgari (needinfo please, extremely long backlog) from comment #40) > Andrea, why did the tests here never land? For security reasons. We didn't land the test together with the patch.
Assignee | ||
Comment 43•7 years ago
|
||
I'll file a bug to land them.
Reporter | ||
Comment 44•6 years ago
|
||
1404910 adds tests to make sure this is fixed.
Flags: needinfo?(ptheriault)
Updated•5 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•