On Mon, Aug 20, 2012 at 5:09 PM, Brian Smith <[email protected]> wrote:
Adam Barth wrote:
The way the implementation in Chrome works is that max-age=0 only
clears the entry for that particular host name. If there's another
shorter host name with includeSubdomains, that isn't affected.
Let me try to clarify with an example, which I think should be explicitly
documented in the spec:
1. We visit https://example.com and receive HSTS with max-age=1234567890 ;
includeSubdomains
2. We visit https://sub.example.com and receive HSTS with max-age=0
Now, is sub.example.com HSTS (because it inherits the HSTS setting from
example.com), or is it non-HSTS (because we received a max-age=0 for that host)?
It is HSTS. Visit (2) would have removed any sub.example.com-specific
entries in the HSTS state table, but there were none, so it didn't
have any effect on the world.
When we receive a HSTS header from sub.example.com with max-age > 0, then we
will treat the expiration time of sub.example.com to be
MAX(expiration(example.com), expiration(sub.example.com)).
A simpler way to think about it is that you keep state for each host.
To answer the question of whether a given host is HSTS, you walk the
list of subdomains and check their unexpired state.
But, if we receive a HSTS header from sub.example.com with max-age == 0, there
are two possibilities:
1. We act consistently with the above case and calculate the HSTS expiration
time of sub.example.com to be:
MAX(expiration(example.com), expiration(sub.example.com))
== MAX(expiration(example.com), 0)
== expiration(example.com)
This means that we would effectively be ignoring the max=age == 0 value
sent by sub.example.com.
Correct.
2. We honor the max-age=0 directive sent by sub.example.com and turn off HSTS for
sub.example.com, but not for example.com. That is, we would treat max-age == 0 from a
subdomain as "do not do includeSubdomains inheritance for this subdomain."
This is not correct. We do "honor" the max-age directive set by
sub.example.com by expiring any sub.example.com-specific state.
However, sub.example.com is HSTS due to state specific to example.com,
which is not expired.
Now, it seems to me that the only reasonable choice is #2, but the spec seems
to imply that we should do #1.
Choice #1 seems reasonable to me.
Here's the problematic scenerio:
1. We visit https://example.com and get the HSTS header with includeSubdomains
and an (effectively) infinite expiration time.
There is no such thing as an infinite expiration time. Let's proceed
assuming you mean "one year" rather than infinite.
2. The owners of example.com decides to turn of HSTS for whatever reason
(perhaps the domain changed owners, or there's a compatibility issue, or
whatever), so they start sending out HSTS with max-age=0 for example.com and
for all the subdomains.
That's not a correct way of disabling HSTS after (1). Instead, they
need only send out an max-age=0 header for example.com itself.
3. We visit https://sub.example.com and get the max-age=0 HSTS header.
If we choose choice #2, we do what the owners of example.com intended, by
treating https://sub.example.com as non-HSTS right away, without ever needing
to visit https://example.com, which we might NEVER do ever again.
I mean, it's just guesswork as to what they intend. I can write a
similar story in which the intent is the reverse.
If we choose choice #1, we will effectively be making https://sub.example.com
HSTS forever, and the domain owner has no way to help us undo it.
They can simply initiate a request to https://example.com/ (e.g., by
using an HTTP redirect or an HTML image element) and clear the HSTS
state for that host name.
Adam