[MIX] 4 possible solutions to the problem of Mixed Content Blocking stalling HTTPS deployment

Apologies for joining the conversation here fairly late, and for doing
so with such a long email...

<TLDR>This email considers four options for fixing the current MCB+HTTPS
deployment trainwreck: 0. give site operators better tools for
navigating the breakage; 1. try to fix mixed content with serverside
proxies; 2. change the deployed HSTS semantics while resolving the
Chrome team's concerns about that; 3. add a new HSTS directive that
makes the HTTPS transition easy for future client populations, leaving
legacy clients with HTTP. My current vote is 3 > 2 > 1 > 0.</TLDR>

As most folks here probably realise, Mixed Content Blocking (MCB) has
had the unintended side effect of making transitions from HTTP to HTTPS
much more difficult for a huge population of sites -- those with large
HTML, JS and serverside codebases that emit same-domain and
cross-domain HTTP urls for historical reasons.  Though MCB is necessary
for HTTPS to have the properties it is supposed to have, it is also
unfortunately adding a vast amount of engineering labor to the HTTPS
deployment roadmap.

Our work with Mozilla et al the Let's Encrypt project and particular the
Let's Encrypt agent https://github.com/letsencrypt/lets-encrypt-preview/ ;
https://www.youtube.com/watch?v=Gas_sSB-5SU has made us acutely aware of
these problems.  As a result of MCB, there are many situations where we
won't be able to automatically redirect HTTP -> HTTPS for a sys admin
without a significant risk of breakage.

I hope everyone can agree that the status quo isn't particularly sane.
Given current clients and servers, the problem of legacy HTTP URLs would
need to be fixed in billions of files on tens of millions of sites.  It
would be a much more pragmatic for us to fix this issue in the ~10
largest Web client codebases, and/or the ~10 largest Web server
codebases.  

So I'd argue that this community needs to pick a strategy to make that
happen.  I'm going to propose four strategies, though I'm keen to hear
others!

0. Really force millions of site operators to edit all their code.  If
we're going to do this and expect to win, we had better provide much,
much better tools for doing it.  Perhaps Let's Encrypt can enable
report-only CSP and host analytics somewhere to tell webmasters where
things are going wrong.  Perhaps, instead of a mysterious MCB shield,
browsers could provide a list of required edits to HTML and JS source
files to fix MC.  Even with measures like this, I believe option 0 would
leave far too much of the work to be done by millions of fallible
humans.

1. Try to deploy automated serverside fixes.  Webservers, or the Let's
Encrypt agent, could ship with a proxy that it commonly interposes
between the HTTP server and TLS termination, which parses HTML, JS, etc,
and tries to identify and fix same-origin mixed content and (where
possible, perhaps by using HTTPS Everywhere rulesets) cross-origin mixed
content.

This could work, but will be a shamefully janky solution.  Parsing HTML
and JS on the serverside has a lot of correctness, performance, and some
security implications we wouldn't be comfortable with.  But without a
change to clients' deployed MCB semantics, I think this is the best we
can do.

OK, so what could client implementors do?

2. Alter their HSTS implementations, so that those help solve rather than
exacerbate mixed content situations.  Perhaps this is only realistic
within first party origins, plus those third party origins that have
themselves enabled HSTS.  Though I do think we should consider a more
ambitious option like this:

 - If a site sets HSTS, all third party resource fetches are attempted
   over HTTPS before being blocked, but if this is happening on 3rd
   party domains that haven't themselves set HSTS, the site gets the
   angry crossed-out HTTPS UI to warn the user and admin that something
   squirrely and potentially dangerous is occurring.  For my money, this
   would be an appropriate response to the conceivable but probably very
   rare case that 3rd party HTTPS upgrades are actually a security
   problem because the 3rd party server does something weird with them.

I know there have been some arguments made against solution 2,
summarised for instance by agl in this November thread:

https://lists.w3.org/Archives/Public/public-webappsec/2014Nov/0307.html

Quoting and replying:

On Wed, Nov 19, 2014 at 10:30 PM, Adam Langley <agl@google.com> wrote:

> Chrome applies mixed-content rules before HSTS redirects are
> considered and it's unlikely that we would change that.
>
> Otherwise sites randomly work or not based on whether the profile has
> previously visited (and thus remembered HSTS for) an origin

Why not try fetching favicon.ico over HTTPS when you've about to block
mixed content, allowing you to get an HSTS header if there's one to be
had?

>
> Also, it leaves mixed-content issues to bite people using browsers
> that don't implement HSTS (and possibly allow dangerous loads).

Browsers that don't implement HSTS basically can't provide a secure
browsing experience for human users anyway.  But I do agree that there's
a bit of a tension between trying to encourage the strongest possible
HTTPS deployments (which is appropriate for the highest-value sites) and
trying to get every last site to a great HTTPS deployment, assuming
that there's a modern client there to help.  Which leads me to option
3...

3. Add a new directive to the HSTS header, which sites (and the Let's
Encrypt agent working on behalf of sites) can set.  It could be called
the "easy" or "helpful" bit.  In slogan form, the semantics of this
would be "if you're a modern client that knows how to do Helpful HSTS,
this site should be entirely HTTPS; if you're an old client that has
MCB/HSTS but doesn't know about Helpful HSTS, leave the site on HTTP".

Assuming that clients are following point 6.1.4 in RFC 6797
(https://tools.ietf.org/html/rfc6797#section-6.1) correctly, it should
be practical to make this kind of functionality part of HSTS.

There's a question about how to get the HSTS Helpful bit to the
client if the server is trying to leave the HTTP version of their site
alive for clients with traditional MCB implementations.

A serverside answer would be to embed a 1x1 image over HTTPS and trigger
HSTS Helpful that way.

A client-side answer would be to request
https://example.com/.well-known/hsts-check at some point during first
or early contact with a domain, and let the upgrade happen then.

The Helpful bit should probably also have a way for site operators to
request and control automatic upgrades of embedded third party
resources.  That could range from "try every third party resource over
HTTPS, all of the time", through a whitelist of domains for which
this should happen, through to the full gory details of putting
something flexible like HTTPS Everywhere rulests in the HSTS directive.

--------------

Okay, so which of these options should we pick?  From first principles I
would probably have gone with option 2, but given that there are so many
copies of Chrome and Firefox with weird HSTS+MCB semantics in the field,
the case for option 3 seems to allow more deployment with less breakage.

We will build and ship 1 if that's all we can do. 0 is a good idea for
sites that have the security engineering resources to do a lot of work
for older clients, but we can't expect that to true of all of the
hundreds of millions of sites that should be switching to HTTPS.

-- 
Peter Eckersley                            pde@eff.org
Technology Projects Director      Tel  +1 415 436 9333 x131
Electronic Frontier Foundation    Fax  +1 415 436 9993

Received on Tuesday, 3 February 2015 09:31:24 UTC