HSTS (HTTP Strict Transport Security ) is a mechanism by which a server can indicate that the browser must use a secure connection when communicating with it. It can be an effective tool for protecting the privacy and security of users and their data.
However, when connecting to an HSTS host for the first time, the browser won’t know whether or not to use a secure connection, because it has never received an HSTS header from that host. Consequently, an active network attacker could prevent the browser from ever connecting securely (and even worse, the user may never realize something is amiss). To mitigate this attack, we have added to Firefox a list of hosts that want HSTS enforced by default. When a user connects to one of these hosts for the first time, the browser will know that it must use a secure connection. If a network attacker prevents secure connections to the server, the browser will not attempt to connect over an insecure protocol, thus maintaining the user’s security.
Our “preload list” has been seeded with entries from Chrome’s list of a similar function. To build our preload list, a request is sent to every host with ‘mode: “force-https”‘ on Chrome’s list. Only if a host responds with a valid HSTS header with an appropriately large max-age value (currently greater than or equal to 10886400, which is eighteen weeks) do we include it in our list. We also see if the includeSubdomains value for the entry on Chrome’s list is the same as what we receive in the response header (if they do not match, we use the one we receive).
We limit the list to hosts that send a large max-age under the assumption that these sites will not revert to non-HSTS status. However, this may become necessary. Suppose ownership of a domain on the preload list is transferred and the new owner decides to no longer use HSTS. The HSTS spec allows the site to send a header with the directive “max-age=0″. This indicates that HSTS should not be enforced for that host, and the browser would honor this. The preload list must replicate this behavior.
To accomplish this task, we introduce the concept of “knockout” entries in our HSTS implementation. When the browser receives an HSTS header with “max-age=0″, a knockout entry is stored that overrides the corresponding entry in the preload list. The knockout entry essentially says, “We have no HSTS information regarding this host.” As a result, the browser behaves as if the host were not on the preload list.
However, the normal rules of the “includeSubdomains” directive still apply. This can result in non-intuitive behavior. Suppose child.example.com is on the preload list, but has delivered a header with the directive “max-age=0″. Further suppose that example.com has sent a header with “includeSubdomains” and a non-expired max-age. The knockout value means the preload list will not be consulted for “child.example.com”. However, since we do have an entry for “example.com” where includeSubdomains is true, child.example.com is still an HSTS host (as is any other subdomain of example.com). Hence the browser will only connect to child.example.com over a secure connection, despite the fact that it has a knockout entry.
In short, HSTS in combination with a preloaded list of sites can be a great tool for increasing the security of users, but care must be taken with the includeSubdomains directive. This feature is currently in Firefox Beta, so download a recent build and give it a spin.
Updated on Nov. 5th, 2012 to clarify the minimum max-age value and to change some formatting.