Http Strict Transport Security (HSTS) is a vital web security policy mechanism that helps to protect websites against man-in-the-middle attacks, such as protocol downgrade attacks and cookie hijacking. It’s a simple yet powerful standard, widely supported by modern browsers, that ensures web browsers always connect to a website over HTTPS. This eliminates the insecure practice of relying on HTTP to HTTPS redirects, which can be vulnerable.
When a browser is informed that a website has enabled HTTP Strict Transport Security, it implements two crucial behaviors:
- Automatic HTTPS Connections: The browser automatically uses an
https://
connection for all requests to the website, even if you typehttp://
in the address bar or follow anhttp://
link. - Bypassing Certificate Warnings: HSTS prevents users from clicking through security warnings related to invalid SSL/TLS certificates, further enhancing security by reducing user error in critical security decisions.
A website signals to browsers that it has activated HSTS by sending a special HTTP header specifically over HTTPS connections.
In its most basic form, an HSTS policy instructs the browser to enable HSTS for the specific domain and its subdomains, remembering this setting for a defined period, specified in seconds:
Strict-Transport-Security: max-age=31536000;
This policy, however, can be significantly strengthened. The most robust and highly recommended form of HTTP Strict Transport Security policy includes all subdomains and expresses a willingness for the domain to be “preloaded” into browsers:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
It is important to note the following when implementing this stronger form:
- The HSTS policy should be deployed on the root domain, for instance,
https://domain.com
, and not onhttps://www.domain.com
. - Crucially, all subdomains associated with the primary domain must support HTTPS. They are not required to have their own HSTS policy but must be accessible via HTTPS.
Further below, you will find practical examples of how to configure an HSTS policy on popular web servers.
Background of HTTP Strict Transport Security
The concept of Strict Transport Security was initially proposed in 2009 as a direct response to vulnerabilities demonstrated by security researchers, notably Moxie Marlinspike’s SSLStrip tool. These demonstrations highlighted how attackers could exploit insecure HTTP to HTTPS redirects to downgrade connections and intercept sensitive data. This led to the rapid adoption of HSTS by major web browsers, and it was officially standardized as RFC 6797 in 2012.
The fundamental problem that HTTP Strict Transport Security addresses is that even websites that support HTTPS often leave a window of vulnerability open. Users might still initiate connections over plain HTTP in several common scenarios:
- Direct URL Entry: When a user types a domain like “example.com” into the browser’s address bar, browsers default to using
http://
. - Following Old Links: Users may click on older bookmarks or links embedded on other sites that mistakenly use
http://
URLs. - Network Attacks: Malicious networks can actively intercept and rewrite
https://
links tohttp://
, forcing a downgrade to an insecure connection.
Websites that prioritize security typically still listen on port 80 (HTTP) to redirect users to the secure HTTPS version. For example, a typical HTTP redirect might look like this:
$ curl --head http://github.com
HTTP/1.1 301 Moved Permanently
Location: https://github.com/
However, this redirect itself is a security risk. During this initial HTTP connection and redirect phase, an attacker can intercept the communication. This interception could expose sensitive information, such as session cookies from previous secure sessions, or maliciously redirect the user to a phishing website designed to steal credentials.
HTTP Strict Transport Security effectively mitigates this risk. By returning the Strict-Transport-Security
header whenever a user successfully connects over HTTPS, the website instructs the browser to remember this preference for future connections. For instance:
$ curl --head https://github.com
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
This header, in this example from GitHub, enables HSTS for github.com
. Once HSTS is active, any subsequent attempt to access http://github.com
will be automatically upgraded by the browser to https://github.com
before the request is even sent.
In the given example, the browser will cache the HSTS policy for one year (max-age=31536000 seconds). This policy is renewed every time the browser encounters the header again during a secure visit. Therefore, as long as a user visits https://github.com
at least once within the max-age
period, they remain continuously protected by HSTS.
HSTS Preloading: Ensuring First-Visit Security
For HTTP Strict Transport Security to be effective, a user’s browser must first receive the HSTS header from the website over a secure HTTPS connection. This implies that a user is not protected by HSTS until after their initial successful secure connection to a particular domain.
This “first visit vulnerability” is further compounded by scenarios where a user might never directly visit the root HTTPS domain, such as:
- Redirection from Root to www: Many websites redirect directly from
http://domain.com
tohttps://www.domain.com
, meaninghttps://domain.com
is never directly accessed. - Redirect-Only Domains: Some domains are solely used for redirects, pointing from
http://domain.com
directly to a final destination likehttps://destination.com
.
In such cases, because https://domain.com
is never visited, browsers will not receive an HSTS policy with the includeSubDomains
directive that would apply to the entire domain zone.
To address this critical first-visit gap, the Chrome security team developed the “HSTS preload list.” This is a built-in list of domains, hardcoded into Chrome, that have HTTP Strict Transport Security enabled by default, even on the very first visit. This list is publicly available and maintained.
The impact of the Chrome HSTS preload list is amplified because it is also incorporated by other major browsers, including Firefox, Safari, Opera, and Edge. This makes HSTS preloading a broadly effective mechanism across the web.
How to Preload Your Domain for HSTS
The Chrome security team provides a public platform where anyone can submit their domain to the HSTS preload list. To be eligible for preloading, your domain must meet specific rigorous requirements:
- HTTPS Everywhere: HTTPS must be enabled on the root domain (e.g.,
https://example.com
) and on all subdomains (e.g.,https://www.example.com
). This is particularly important for thewww
subdomain if a DNS record exists for it. This requirement extends to all subdomains, including those used solely on internal networks. - Comprehensive HSTS Policy: The HSTS policy must include all subdomains (
includeSubDomains
directive), specify a substantialmax-age
to ensure long-term enforcement, and include thepreload
flag to explicitly consent to preloading. - HTTP to HTTPS Redirection: The website must redirect from HTTP to HTTPS, at least on the root domain, to ensure all initial HTTP attempts are securely upgraded.
A typical and valid HSTS header suitable for preloading looks like this:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Looking ahead, as the web increasingly migrates to HTTPS entirely, and as browsers potentially begin to phase out support for plain HTTP and default to HTTPS connections, the HSTS preload list (and perhaps HSTS itself) might eventually become less critical.
Until that future state is reached, however, the HSTS preload list offers a simple and highly effective method for firmly establishing HTTPS across an entire domain and ensuring robust security from the very first connection.
HSTS as a Force for Organizational HTTPS Adoption
Beyond its direct security benefits for website visitors, HTTP Strict Transport Security serves a valuable secondary purpose as an organizational tool to enforce and track HTTPS adoption.
When a domain owner adheres to best practices and sets an HSTS policy on their base domain with includeSubDomains
and preload
, it signifies a strong and auditable commitment: “Every part of our web infrastructure is, and always will be, accessible over HTTPS.” This declaration empowers browsers to rigorously enforce this policy from that point forward.
This commitment provides a clear and measurable metric, offering those responsible for overseeing an organization’s transition to HTTPS a definitive way to mark domains as “completed” and securely configured.
Taking a broader perspective, it is even technically feasible to preload HSTS for entire top-level domains (TLDs), as Google pioneered with .google
. For smaller, centrally managed TLDs, such as .gov
, achieving similar top-level HSTS preloading could be a future possibility, further strengthening internet security at scale.
Configuration Examples for Common Web Servers
Implementing HTTP Strict Transport Security is straightforward on most common web servers. Here are configuration examples for popular platforms:
Nginx:
On Nginx servers, you can add an add_header
command within the appropriate virtual host configuration block. For example, to enforce HSTS, you would add:
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload;' always;
This line ensures the HSTS header is always included in HTTPS responses.
Apache:
For Apache web servers, you can use the Header
directive to always set the HSTS header. Add the following line to your Apache configuration file within the virtual host section:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
This configuration ensures that the HSTS header is consistently sent with HTTPS responses.
Microsoft IIS (Internet Information Services):
For servers running Microsoft IIS, configuration is managed through the web.config
file. For IIS 7.0 and later, the following web.config
snippet handles both HTTP to HTTPS redirection and enables HSTS for HTTPS connections:
<rule> name="HTTP to HTTPS redirect" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" ignoreCase="true" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule> <rule> name="Add Strict-Transport-Security when HTTPS" enabled="true"> <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" /> <conditions> <add input="{HTTPS}" pattern="on" ignoreCase="true" /> </conditions> <action type="Rewrite" value="max-age=31536000; includeSubDomains; preload" /> </rule>
This configuration first redirects HTTP requests to HTTPS and then adds the HTTP Strict Transport Security header to all HTTPS responses.
In general, the key is to configure your web server to set a custom HTTP header named Strict-Transport-Security
with the value max-age=31536000; includeSubDomains; preload
(or a suitable variant based on your specific needs).
Resources
- MDN Web Docs on HSTS: HTTP Strict Transport Security
- RFC 6797 – HTTP Strict Transport Security (HSTS): tools.ietf.org/html/rfc6797
- HSTS Preload Submission: hstspreload.org
- Can I use… Strict Transport Security: caniuse.com/#feat=stricttransportsecurity