Re: [websec] HSTS: max-age=0 interacting with includeSubdomains

Adam Barth <ietf@adambarth.com> Tue, 21 August 2012 00:20 UTC

Return-Path: <ietf@adambarth.com>
X-Original-To: websec@ietfa.amsl.com
Delivered-To: websec@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id EA24711E809A for <websec@ietfa.amsl.com>; Mon, 20 Aug 2012 17:20:04 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.677
X-Spam-Level:
X-Spam-Status: No, score=-2.677 tagged_above=-999 required=5 tests=[AWL=-0.300, BAYES_00=-2.599, FM_FORGED_GMAIL=0.622, J_CHICKENPOX_33=0.6, RCVD_IN_DNSWL_LOW=-1]
Received: from mail.ietf.org ([64.170.98.30]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id FhKzg+EKx-cc for <websec@ietfa.amsl.com>; Mon, 20 Aug 2012 17:20:04 -0700 (PDT)
Received: from mail-gh0-f172.google.com (mail-gh0-f172.google.com [209.85.160.172]) by ietfa.amsl.com (Postfix) with ESMTP id 4847A11E8097 for <websec@ietf.org>; Mon, 20 Aug 2012 17:20:04 -0700 (PDT)
Received: by ghbg16 with SMTP id g16so6087547ghb.31 for <websec@ietf.org>; Mon, 20 Aug 2012 17:20:03 -0700 (PDT)
Received: by 10.236.191.233 with SMTP id g69mr23479494yhn.113.1345508403896; Mon, 20 Aug 2012 17:20:03 -0700 (PDT)
Received: from mail-vb0-f44.google.com (mail-vb0-f44.google.com [209.85.212.44]) by mx.google.com with ESMTPS id o25sm31856158yhm.14.2012.08.20.17.20.02 (version=SSLv3 cipher=OTHER); Mon, 20 Aug 2012 17:20:02 -0700 (PDT)
Received: by vbbez10 with SMTP id ez10so6830127vbb.31 for <websec@ietf.org>; Mon, 20 Aug 2012 17:20:01 -0700 (PDT)
Received: by 10.52.96.33 with SMTP id dp1mr1680048vdb.67.1345508401352; Mon, 20 Aug 2012 17:20:01 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.58.64.169 with HTTP; Mon, 20 Aug 2012 17:19:31 -0700 (PDT)
In-Reply-To: <1883526372.2436253.1345507760090.JavaMail.root@mozilla.com>
References: <CAJE5ia91-j4avKvvKSUj2P1K_U=EFwGd+feVqMNv8AtkWqSA7Q@mail.gmail.com> <1883526372.2436253.1345507760090.JavaMail.root@mozilla.com>
From: Adam Barth <ietf@adambarth.com>
Date: Mon, 20 Aug 2012 17:19:31 -0700
Message-ID: <CAJE5ia_YpQ5WSJBwUWdeNZcc_SGRQQNqZpQnTU0BXK7Yju3yqA@mail.gmail.com>
To: Brian Smith <bsmith@mozilla.com>
Content-Type: text/plain; charset="ISO-8859-1"
Cc: websec@ietf.org
Subject: Re: [websec] HSTS: max-age=0 interacting with includeSubdomains
X-BeenThere: websec@ietf.org
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: Web Application Security Minus Authentication and Transport <websec.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/websec>, <mailto:websec-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/websec>
List-Post: <mailto:websec@ietf.org>
List-Help: <mailto:websec-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/websec>, <mailto:websec-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 21 Aug 2012 00:20:05 -0000

On Mon, Aug 20, 2012 at 5:09 PM, Brian Smith <bsmith@mozilla.com> 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