Subject: [websec] Safari restrictions to HSTS

From: John Wilander <[email-masked]>
Date: Tue, 30 Jan 2018 13:51:45 -0800

Hi WebSec @ IETF!

My name is John Wilander and I’m a security engineer on Apple’s WebKit team. WebKit, and thus our browser Safari, has some special rules for (non-preload) HSTS to mitigate HSTS super cookies. I’m sending over the details in case you want to augment the HSTS specification.

Basic rule: Only allow first parties to set HSTS.

If it’s a response to a top frame load that has an HSTS header, it is obviously the first party so that's automatically handled. If it’s a response to a subresource request, it gets more interesting.

As of our latest releases, we only allow the current first-party domain and its eTLD+1 (formally public suffix + 1) to set HSTS in subresource responses.

Example:

Say you have loaded a page from https://sub.domain.example.com <https://sub.domain.example.com/>. A response to a subresource request on that page may set HSTS for:
sub.domain.example.com <http://sub.domain.example.com/> and
example.com <http://example.com/>
It may not set HSTS for:
some.sub.domain.example.com <http://some.sub.domain.example.com/>,
domain.example.com <http://domain.example.com/>, or
other.org <http://other.org/>
   Kind regards, John Wilander

---

From: Lucas Garron <[email-masked]>
Date: Mon, 05 Feb 2018 21:58:52 +0000

While I think it is is good to fight supercookies, I'd like to note that
this kind of policy has performance implications.

Suppose a site has a domain named short.example that redirects to
longsitename.example:

   - http://short.example
      - Redirect
   - https://longsitename.example

(Real-world examples: fb.me, bofa.com, bit.ly, t.co)

Neither step in the redirect can set an HSTS header for the short.example
host, which means that subsequent visits will not be protected. Caching or
using permanent redirect codes can help, but are not as strong as HSTS (the
site's caching max-age may not be as high, may be cleared with browsing
data more easily, or may be evicted from cache by browsers more easily) and
usually only applies to exact URLs – this will not work if short.example is
e.g. a URL shortener with different URLs for different visits.

It is possible to fix this by redirecting to HTTPS before going to another
site:

   - http://short.example
   - Redirect
   - https://short.example
   - Set HSTS
      - Redirect
   - https://longsitename.example

In fact, https://hstspreload.org/ currently enforces this as a dynamic HSTS
best practice if you want to submit short.example to the HSTS preload list.
However, for dynamic HSTS this incurs the performance penalty of an
additional synchronous blocking HTTPS request for the first load – and back
when I was maintaining the preload list I received a few concerned emails
about this penalty. (Note that the performance penalty goes away for users
who have short.example in their browser's HSTS preload list. But there is a
multi-week gap while this affects all users before the preloaded site
reaches their browser, and this will always affect users with clients that
don't have an up-to-date HSTS preload list. Also, we may soon see a feature
where not all sites on the preload list are shipped to all browser users.)

If the response from https://longsitename.example is permitted to set HSTS
for short.example, this has two benefits:

   - http://short.example always gets users to the final destination
   without a performance penalty.
   - *All* visits to https://longsitename.example can "prime" HSTS
   for short.example in case visitors use it in the future.
      - In fact, the main site can pre-emptively prime HSTS for *multiple*
      related sites without adding redirect hops for each one.

This is currently possible in browsers other than Safari by requesting
extra subresources, although it would be nice to have something more
declarative <https://bugs.chromium.org/p/chromium/issues/detail?id=626180>.

I think it would be nice if any cross-domain restrictions did not introduce
dynamic HSTS security vs. performance tradeoffs for legitimate use cases
like I described.

One hacky way to solve this for my main example would be to allow HTTP
responses to set an HSTS header for the domain while redirecting to another
domain, but this contradicts the current spec and makes it easy to brick a
site. (It would also not support general cross-domain priming.)

»Lucas

On Mon, Feb 5, 2018 at 8:08 AM John Wilander <[email-masked]> wrote:

> Hi WebSec @ IETF!
>
> My name is John Wilander and I’m a security engineer on Apple’s WebKit
> team. WebKit, and thus our browser Safari, has some special rules for
> (non-preload) HSTS to mitigate HSTS super cookies. I’m sending over the
> details in case you want to augment the HSTS specification.
>
> If it’s a response to a top frame load that has an HSTS header, it is
> obviously the first party so that's automatically handled. If it’s a
> response to a subresource request, it gets more interesting.
>
> As of our latest releases, we only allow the current first-party domain
> and its eTLD+1 (formally public suffix + 1) to set HSTS in subresource
> responses.
>
> Example:
>
> Say you have loaded a page from https://sub.domain.example.com. A
> response to a subresource request on that page may set HSTS for:
>
>    1. sub.domain.example.com and
>    2. example.com
>
> It may not set HSTS for:
>
>    1. some.sub.domain.example.com,
>    2. domain.example.com, or
>    3. other.org
>
> _______________________________________________
> websec mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/websec
>