Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mixed-content XHR & Websockets

417 views
Skip to first unread message

Nicholas Wilson

unread,
Jul 23, 2013, 9:34:37 AM7/23/13
to dev-se...@lists.mozilla.org, br...@briansmith.org
Hello,

I'd like to ask about the possibility of changes to the way
mixed-content XHR and WebSockets are flagged up.

(I should start by saying that the new mixed-content blocker is great
and that tightening restrictions on these sorts of things is in
general excellent.)

Firstly, I think it's a problem that we can't make mixed-content
WebSocket connections. I realise this has in been in Firefox for a
while, but I haven't written any Firefox patches for a few years and
missed the change. Now that XHR is being blocked, it might be a
suitable point to gently revisit this? I think the security issues for
mixed-content WebSockets and XHR are essentially the same, so it would
be good to use the same checks for both.

That is, we now have UI in firefox for approving a mixed-content XHR:
I'd like that same UI to be pulled in for the WebSockets case. I made
a patch for that today (it's small). It's not really acceptable for us
to ask our customers to twiddle the
network.websocket.allowInsecureFromHTTPS preference, but the UI in the
address bar is just about bearable for a product to require users to
click through.

I think having uniformity here is clearly helpful. I do recognise that
the WebSocket API spec requires mixed-content connections to be
blocked, but there might still be room for discussion on the benefits
of it, especially while you're adjusting the model for XHR at the same
time.

Without this change, we're going to have to release our product with
long polling in Firefox just because we can't create a WebSocket! It's
my fault I guess that we got quite far in our development before
testing over HTTPS with Firefox and noticing the problem with a shock.
Our webapp is a client that does its own crypto: imagine if you wanted
to do a webapp version of an SSH or VNC client. We've got asm.js to
work with OpenSSL, and also use WebCrypto. This is exactly what rich
webapps should be like: without downloading OpenSSH, you can run the
client in your browser as part of a web dashboard. WebSockets were
created to enable exactly these sorts of use cases, surely! It's clear
though that the app has to be served over HTTPS. And, it makes
connections to WebSocket-enabled servers on your local network that
aren't on the wide internet, so it's infeasible to roll out a
globally-recognised TLS certificate to each machine that the dashboard
manages. So, we can't do the WebSockets over TLS, the hosting page has
to be HTTPS, and Firefox currently doesn't permit that use-case.

So, the first request was small: would you accept the patch to pull in
the mixed-content UI for WebSockets, the same as for XHR, so that at
least there's some way for our customers to use Firefox without having
to edit about:config. (Larry still says, "Other people can view or
modify the website's behaviour", which is untrue... but we can live
with that.)

The second request is a bigger discussion: I think we need a fuller,
proper way to allow mixed-content XHR/WebSocket. Not all mixed-content
requests, just some. I recognise the value that browsers provide to
website developers flagging up when their site is misconfigured, and
we want these warnings to be on by default.

What some webapps need is a way for the warning to be turned off
selectively. I remember the coverage when noVNC first came out and
people were saying how cool it was. It's a shame that sort of webapp
can't be served over HTTPS to Firefox. The mixed-content diagnostic is
intended to "motivate" site admins to fix their site, in the common
case the resource loading is unsafe, but for us it's getting in the
way of providing an application to customers which is actually secure.

The general principle is that both XHR and WebSockets can be used
virtuously and securely in mixed-content scenarios, and these are
use-cases you aren't yet enabling. (To be fair, the only examples of
mixed-content XHR I can think of are fairly contrived: an HTTPS page
that loads some resources over HTTP and checks their hashes against a
list served with the HTTPS page before executing them. This could very
substantially reduce load on a CDN.)

I tentatively suggest a new header: "Access-Control-Security:
externally-verifiable" (or anything similar). If set on a response, we
allow it even in a mixed-content context, and trust the JavaScript to
do the verification. It's simple and should keep everyone happy: the
default case still produces the warnings, but authors with a genuine
use-case can take on the responsibility of validating the content. It
could perhaps be set only on replies if the header
"Access-Control-Request-Security: tls-context" is set. (These are
probably rubbish header names, but that's not relevant to the idea.)
The connection is over unsecured HTTP, so an attacker can modify these
headers at will. That's OK though; the security model doesn't rely on
the integrity of the request headers.

Thanks for reading a long email,
Nick Wilson


On a related note, in #662692, Brian Smith said "IMO, the SSH example
is better off using mozTCPSocket" I'm not sure about that; while it's
clearly great for chrome-context code or browser extensions, I still
don't see how Mozilla could open this up to the webpages more
generally. For geolocation, the "share your location" prompt is
readily understandable, but you'll struggle to come up with suitable
wording for mozTCPSocket. If even 5% of users misunderstand it and
grant the permission to a drive-by intranet scanner, it'll send IT
admins crazy. You may find it's just too powerful to give to webpages,
and that the mandatory server-side Origin control for WebSockets makes
it the right choice of API to offer webapps. In any case, that's
another discussion, but to me it looks like providing some UI to relax
the mixed-content restriction is much smaller than providing a UI for
ordinary webapps to elevate themselves to full local network access.

-----
Nicholas Wilson: nich...@nicholaswilson.me.uk
Cambridge, CB4 2TU

Gervase Markham

unread,
Jul 24, 2013, 12:22:39 PM7/24/13
to mozilla-de...@lists.mozilla.org
On 23/07/13 14:34, Nicholas Wilson wrote:
> created to enable exactly these sorts of use cases, surely! It's clear
> though that the app has to be served over HTTPS. And, it makes
> connections to WebSocket-enabled servers on your local network that
> aren't on the wide internet, so it's infeasible to roll out a
> globally-recognised TLS certificate to each machine that the dashboard
> manages. So, we can't do the WebSockets over TLS, the hosting page has
> to be HTTPS, and Firefox currently doesn't permit that use-case.

Have you considered giving the managed servers certs minted from a local
company CA, and trusting that root cert in the copies of Firefox? Or
does that not work either?

Gerv


Nicholas Wilson

unread,
Jul 25, 2013, 8:18:18 AM7/25/13
to Gervase Markham, dev-se...@lists.mozilla.org
On 24 July 2013 17:22, Gervase Markham <ge...@mozilla.org> wrote:
> Have you considered giving the managed servers certs minted from a local
> company CA, and trusting that root cert in the copies of Firefox? Or
> does that not work either?

Gervase,

Thanks for that idea. We did try thinking through all the
possibilities here, but none of them is especially attractive.
Hopefully this isn't too thorough:

1) The servers have self-signed certs. We can distribute them for the
user via our web service, so that when the user tries to make a
connection, we download the cert over HTTPS for them and give them
some UI leading them through the process of adding it to the trust
store for their platform/browser. This isn't great because we'd have
to add it to the OS's trust store for Chrome on Windows, for example.
We can't clean the cert up when we're done with it, and the user has
to go through this process for each and every connection.

2) The servers have certs signed by us. We'd have to run a big
operation generating certs for our customers who have millions of
machines between them; when they install our software on a new machine
(which happens all the time) we'd have to have the server do a CSR
that's automatically granted. We just have to trust the node
connecting in that it's asking for a cert for an address/hostname it
really has because it's going to be behind a corporate firewall. The
implication of that is that we still can't leave the crypto up to the
browser: we have to do another key exchange and validation in our
webapp against the peer's credentials as transferred via our system,
because the HTTPS layer isn't protecting against spoofing, it's just
there so the browser lets us make a WebSocket. We can't realistically
verify the CSRs, we just have to sign basically any and every
certificate a customer's install sends us in this model.

Another sticky implication is that the cert we manage has to be a CA
cert. Whether or not it's per-customer, it's not great to have to ask
anyone to put that in the trusted store or their OS or browser, and
it's a burden on us to manage that responsibility.

3) We tell customers they need to generate their certs. This frees us
of some of the burden, and we still handle distributing the cert via
our web service, but it isn't a great model for non-technical users.

Other issues:
*) We'd need to careful about multi-homed hosts with multiple DNS
names or IP addresses. The peer's server probably needs to keep
several certs on hand, one for each IP a peer might try and connect
with.
*) Users simply might not be able to install certs in some
environments (Group Policy can lock down the OS cert store that
IE/Chrome share).

There's another possibility: would a browser ever give a web page an
API to install a cert that's valid only for connections from its
security context, or specify the cert in a URI perhaps? We could
certainly pass the browser something along the lines of
"tlscert:sig:xxxxx:uri:wss://192.168.1.1:5800". Via our webservice we
could get the peer's expected cert. Even if Firefox implemented this
though, it's hardly likely get cross-browser support quickly. I can't
give you a patch this at all quickly, and I doubt you want it either.

To conclude, this really doesn't feel like the path of least
resistance. Our web page knows the peer's identity, we're doing our
own crypto for our protocol, and it doesn't feel "webapp-y" to have to
save the peer's identity information out of the page and into the
browser's global store, when all we want to do is make an outgoing
connection from our page to a peer whose identity we know. In this
case, TLS is a faff and doesn't feel like a natural fit for
peer-to-peer. It doesn't even feel more virtuous to have TLS handle
the crypto, when we can call the browser's same OpenSSL RSA and AES
routines via the WebCrypto API, but with the added benefit that we
know exactly what the peer's RSA pubkey is and can hand it the peer's
key in JWK very naturally in our webapp. We can write an appropriate
UI for our service, whereas relying on the browser's UI or even the
platform cert store is too much out of our control and makes it hard
to write a solution that works in all browsers.

tl;dr -
The web should be a platform for writing network applications that can
replace desktop applications with a page in the browser. We have so
many of the pieces in place: fast asm.js-formatted JavaScript;
WebCrypto in Mozilla and IE11 and Chrome via NaCl; and of course
canvas. The only piece we're struggling with is making an outgoing
WebSocket connection (in Firefox/IE). We'd rather not be forced down
the TLS route and have to delegate our UX to the very varied
certificate management across browsers.

Thanks for your time.
Nick

-----
Nicholas Wilson: nich...@nicholaswilson.me.uk
Site and blog: www.nicholaswilson.me.uk
6 Tribune Court, CB4 2TU
07845 182898

Gervase Markham

unread,
Jul 29, 2013, 6:20:56 AM7/29/13
to Nicholas Wilson
On 25/07/13 13:18, Nicholas Wilson wrote:
> On 24 July 2013 17:22, Gervase Markham <ge...@mozilla.org> wrote:
>> Have you considered giving the managed servers certs minted from a local
>> company CA, and trusting that root cert in the copies of Firefox? Or
>> does that not work either?
>
> Gervase,
>
> Thanks for that idea. We did try thinking through all the
> possibilities here, but none of them is especially attractive.

Thanks for the rundown.

I hope I haven't derailed your thread, in that I'm not the guy who can
approve your patch - I was just trying to help with your problem. But I
agree that either:

a) a patch to allow the user to approve mixed content WebSockets in the
same way as XHR; or

b) a patch to allow the JS to pass a "cert to trust" when it makes an
HTTPS WebSocket connection

would be an OK thing.

Gerv

Stefan Arentz

unread,
Jul 29, 2013, 12:47:16 PM7/29/13
to Gervase Markham, Nicholas Wilson, mozilla-de...@lists.mozilla.org
Can CSP play a role here?

What if my site is on https://foo.com and I set connect-src to http://foo.com ? Would that override the mixed content blocking? If not, is that something we should implement?

Sent from my iPad
> _______________________________________________
> dev-security mailing list
> dev-se...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-security

Nicholas Wilson

unread,
Jul 30, 2013, 8:42:55 AM7/30/13
to Stefan Arentz, mozilla-de...@lists.mozilla.org
On 29 July 2013 17:47, Stefan Arentz <sar...@mozilla.com> wrote:
> Can CSP play a role here?
>
> What if my site is on https://foo.com and I set connect-src to http://foo.com ? Would that override the mixed content blocking? If not, is that something we should implement?
>

Interesting idea. I'm pretty sure we don't do this now (remembering
the code; untested). Indeed, the idea of CSP is for a page to lock
down the external sources, not open them up.

Rather than setting a CORS-style header on the WebSocket resource
("X-Access-Control-Security: externally-verifiable"), we could make a
new CSP header for the hosting page ("X-Content-Security-Policy-Allow:
connect-src 'http-self'") to add in extra policy options for the page.

It's hard to say which is better. Perhaps the per-resource CORS
approach is preferable.


Nicholas

Nicholas Wilson

unread,
Jul 30, 2013, 11:25:45 AM7/30/13
to Daniel Veditz, dev-se...@lists.mozilla.org, Brian Smith
On 27 July 2013 02:18, Daniel Veditz <dve...@mozilla.com> wrote:
> Uniformity is indeed important. Are you implying that some other browser
> is NOT blocking mixed-content WebSockets? Why is it only Firefox where
> you have to do long polling?
>
> If so we can take that information back to the standards body and
> discuss changing the spec (which is probably where this conversation
> should happen).

Thanks, Dan. Chrome certainly doesn't block mixed-content WebSockets
(just checked their latest nightly). They had a patch, but chose not
to commit it.

I'm raising this issue with Firefox because I don't know how to talk
to IE developers, Chrome works for me, and as I understand the
discussion, Firefox was one of the reasons this was added to the spec.
It would be great if we could tweak the spec, but I think you're the
first people I need to convince to do that!

For completeness, we're just checking the whole range of browsers at the moment.

>> The second request is a bigger discussion: I think we need a fuller,
>> proper way to allow mixed-content XHR/WebSocket. Not all mixed-content
>> requests, just some. I recognise the value that browsers provide to
>> website developers flagging up when their site is misconfigured, and
>> we want these warnings to be on by default.
>
> I do want to recognize this as a separate point and don't want it to get
> buried. Leaving WebSockets aside is it appropriate to treat data
> connections as "active" content rather than "passive" content. What do
> IE and Chrome (who both block mixed active content) do with XHR?

I haven't tested with IE yet. Current Chrome is happy with
mixed-content XHR, nightly build displays a warning on load but allows
it. This is different to Firefox, where nightly blocks by default and
provides a UI to reload the page with mixed XHR enabled (at which
point it shows an identical warning to Chrome's).

XHR is probably too dangerous to be passive. It's true you can be
virtuous with it, but it makes sense to be heavy-handed and treat it
as active. It's just too tempting for people to put HTML with script
fragments in there. It's clearly very different from an image or
stylesheet, which could never be interpreted, whereas (X)HTML can
certainly contain executable scripts. It would be possible to treat
XHR as active or passive depending on the content-type, so that only
the (X)HTML, JavaScript, and SVG types were classed as active, but
that might be too much work for a minor bit of behaviour.

As I understand from Chromium bugzilla, there are perhaps one or two
other types of resource types where you differ on whether it counts as
active or passive (some font types?).

>> I tentatively suggest a new header: "Access-Control-Security:
>> externally-verifiable" (or anything similar).
>
> That's worth considering.

I can clean up my patch and post it in a bugzilla as
"X-Access-Control-Security", but perhaps more people need to buy-in
before it's worth doing that.

Best,
Nicholas


-----
Nicholas Wilson: nich...@nicholaswilson.me.uk

Nicholas Wilson

unread,
Jul 30, 2013, 12:27:28 PM7/30/13
to Daniel Veditz, dev-se...@lists.mozilla.org
> On 27 July 2013 02:18, Daniel Veditz <dve...@mozilla.com> wrote:
>> Uniformity is indeed important. Are you implying that some other browser
>> is NOT blocking mixed-content WebSockets?
>
> For completeness, we're just checking the whole range of browsers at the moment.

OK, thanks to a helpful intern we have the full run-down:

Browsers that block mixed-content WebSockets:
* Firefox (v22 & v23 tested, on Win/OSX/Ubuntu)
* Firefox mobile (v22 on Android)
* IE 10 and 11-preview (Windows 7)
* IE 10 on SurfaceRT

Browsers that allow mixed-content WebSockets:
* Chrome (vv28-30 tested, on Win/OSX/Ubuntu)
* Safari (v5 & v6 tested on Win/OSX)
* Opera (v15 & v16-next on Win/OSX)
* Safari on iOS 6
* Chrome 28 on iOS 6
* Chrome (v18 as stock browser on Android 4.2 on an S4, and v28
installed from Play)
* Opera mobile (v14, v12 "Classic" on Android)

Browsers without WebSockets at all:
* IE 8, 9
* Opera mini
* Opera 12

Test details: open https://www.websocket.org/echo.html. Make a wss://
connection. Make a ws:// connection.

So IE and Firefox are on one side, Opera and Chrome and Safari on the
other. Hardly any mobile browser users are having mixed-content
WebSockets blocked.

Tanvi Vyas

unread,
Aug 13, 2013, 7:04:50 PM8/13/13
to dev-se...@lists.mozilla.org
Just want to add a few notes here.

Firefox has blocked Mixed Content websockets for a long time; this is
enforced in the websockets code itself. Because of this, the new Mixed
Content Blocker code returns early when it see's a websocket request -
http://mxr.mozilla.org/mozilla-central/source/content/base/src/nsMixedContentBlocker.cpp#249.
Hence, MCB has punted to the websocket code to make decisions about what
to allow/deny.

Firefox and Chrome's definition of Mixed Active Content differs in 3
main ways. Firefox treats mixed iframes, xhr, and fonts as active
content. In Chrome 30, mixed iframes will move to the active category
(you can test this out in the current Chrome Canary). Chrome is also
planning to move mixed xhr to the active category soon (but I don't know
exactly when). When this happens, the only difference in our
implementations will be mixed content fonts. External fonts are not
that common and mixed content fonts don't break the web since browsers
will just fall back to the default, so I'm not too worried about this.

Nicholas Wilson

unread,
Oct 9, 2013, 12:21:58 PM10/9/13
to Tanvi Vyas, dev-se...@lists.mozilla.org
Thanks Tanvi,

I'd like to wake up this thread a bit. I've just filed
https://bugzilla.mozilla.org/show_bug.cgi?id=924957 and attached a
patch which implements the behaviour I'd like to see, and which I
described earlier on this list. The reception was cautiously positive.
Now I've got round to cleaning up the code, I'm hoping to get some
concrete feedback on the approach.

I'm trying very carefully to minimize the impact of the changes, to
increase the chance it'll actually be accepted cross-browser. I asked
the WHATWG list for feedback
(http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2013-October/040972.html)
and didn't get much, but I am hopeful the tweak I'm suggesting here
will be acceptable to everyone. One of Firefox or Chrome has to agree
to change their approach to bring uniformity!

Accepting the patch is basically a blocker for us to port our Chrome
VNC Viewer to Firefox. Another thread on this list popped up last
month from another developer who needs the ability to run peer-to-peer
WebSocket connections from a secure page ("Security error when trying
to set a non SSL/TLS Websocket from a https page"), so we're clearly
not the only people trying to port desktop application to Firefox as
webapps and running into this problem.

Best,
Nicholas

-----
Nicholas Wilson: nich...@nicholaswilson.me.uk


0 new messages