Strict-Transport-Security 头
HTTP Strict-Transport-Security 响应头(通常缩写为 HSTS)通知浏览器只能使用 HTTPS 访问主机,并且将来任何尝试使用 HTTP 访问它的请求都应自动升级到 HTTPS。此外,在将来连接到主机时,浏览器将不允许用户绕过安全连接错误,例如无效证书。HSTS 仅通过其域名识别主机。
语法
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload
指令
max-age=<expire-time>-
浏览器应记住只能使用 HTTPS 访问主机的时间,以秒为单位。
includeSubDomains可选-
如果指定此指令,HSTS 策略也适用于主机域的所有子域。
preload可选 非标准-
有关详细信息,请参阅预加载严格传输安全。使用
preload时,max-age指令必须至少为31536000(1 年),并且必须存在includeSubDomains指令。
描述
Strict-Transport-Security 头通知浏览器所有与主机的连接都必须使用 HTTPS。尽管它是一个响应头,但它不影响浏览器如何处理当前响应,而是影响它如何发出未来的请求。
当 HTTPS 响应包含 Strict-Transport-Security 头时,浏览器会将主机的域名添加到其 HSTS 主机持久列表中。如果域名已在列表中,则更新过期时间和 includeSubDomains 指令。主机仅通过其域名识别。IP 地址不能是 HSTS 主机。HSTS 适用于主机的所有端口,无论请求使用了哪个端口。
在加载 http URL 之前,浏览器会根据其 HSTS 主机列表检查域名。如果域名与 HSTS 主机进行不区分大小写的匹配,或者是指定了 includeSubDomains 的子域,则浏览器会将 URL 方案替换为 https。如果 URL 指定端口 80,浏览器会将其更改为 443。任何其他显式端口号保持不变,浏览器使用 HTTPS 连接到该端口。
如果连接到 HSTS 主机时发生 TLS 警告或错误(例如无效证书),浏览器不会向用户提供继续或“点击”错误消息的方式,这会损害严格安全的意图。
注意:主机必须仅通过 HTTPS 发送 Strict-Transport-Security 头,而不是不安全的 HTTP。如果通过 HTTP 发送,浏览器会忽略该头,以防止中间人攻击 (MITM) 更改该头以使其过早过期,或为不支持 HTTPS 的主机添加该头。
过期
每次浏览器收到 Strict-Transport-Security 头时,它都会通过将 max-age 添加到当前时间来更新主机的 HSTS 过期时间。对 max-age 使用固定值可以防止 HSTS 过期,因为每个后续响应都会将过期时间推迟到将来。
如果以前发送过 Strict-Transport-Security 头的主机的响应中缺少该头,则以前的头会一直有效,直到其过期时间。
要禁用 HSTS,请设置 max-age=0。这仅在浏览器发出安全请求并收到响应头后才生效。根据设计,您不能通过不安全的 HTTP 禁用 HSTS。
子域
includeSubDomains 指令指示浏览器也将域的 HSTS 策略应用于其子域。一个针对 secure.example.com 且带有 includeSubDomains 的 HSTS 策略也适用于 login.secure.example.com 和 admin.login.secure.example.com。但它不适用于 example.com 或 insecure.example.com。
即使超域使用 includeSubDomains,每个子域主机也应在其响应中包含 Strict-Transport-Security 头,因为浏览器可能在超域之前联系子域主机。例如,如果 example.com 包含带有 includeSubDomains 的 HSTS 头,但所有现有链接都直接指向 www.example.com,则浏览器永远不会看到 example.com 的 HSTS 头。因此,www.example.com 也应发送 HSTS 头。
浏览器独立存储每个域和子域的 HSTS 策略,无论 includeSubDomains 指令如何。如果 example.com 和 login.example.com 都发送 HSTS 头,浏览器会存储两个独立的 HSTS 策略,它们可以独立过期。如果 example.com 使用了 includeSubDomains,则如果其中一个策略过期,login.example.com 仍然受到保护。
如果 max-age=0,includeSubDomains 没有效果,因为指定 includeSubDomains 的域会立即从 HSTS 主机列表中删除;这不会删除每个子域的单独 HSTS 策略。
不安全的 HTTP 请求
如果主机接受不安全的 HTTP 请求,它应使用在 Location 头中具有 https URL 的永久重定向(例如状态码 301)进行响应。重定向不得包含 Strict-Transport-Security 头,因为请求使用了不安全的 HTTP,但该头必须仅通过 HTTPS 发送。在浏览器遵循重定向并使用 HTTPS 发出新请求后,响应应包含 Strict-Transport-Security 头,以确保将来尝试加载 http URL 将立即使用 HTTPS,而无需重定向。
HSTS 的一个弱点是,它直到浏览器与主机建立至少一个安全连接并收到 Strict-Transport-Security 头后才生效。如果浏览器在知道主机是 HSTS 主机之前加载不安全的 http URL,则初始请求容易受到网络攻击。预加载可以缓解此问题。
严格传输安全示例场景
-
在家中,用户首次访问
http://example.com/。 -
由于 URL 方案是
http且浏览器在其 HSTS 主机列表中没有它,因此连接使用不安全的 HTTP。 -
服务器响应
301 Moved Permanently重定向到https://example.com/。 -
浏览器发出新请求,这次使用 HTTPS。
-
通过 HTTPS 发出的响应包含该头
httpStrict-Transport-Security: max-age=31536000; includeSubDomains浏览器记住
example.com是一个 HSTS 主机,并且它指定了includeSubDomains。 -
几周后,用户在机场并决定使用免费 Wi-Fi。但不知情地,他们连接到一个运行在攻击者笔记本电脑上的流氓接入点。
-
用户打开
http://login.example.com/。因为浏览器记住example.com是一个 HSTS 主机并且使用了includeSubDomains指令,所以浏览器使用 HTTPS。 -
攻击者使用伪造的 HTTPS 服务器拦截请求,但没有该域的有效证书。
-
浏览器显示无效证书错误,并且不允许用户绕过它,从而防止他们将密码提供给攻击者。
预加载严格传输安全
Google 维护一个 HSTS 预加载服务。通过遵循指南并成功提交您的域,您可以确保浏览器仅通过安全连接连接到您的域。虽然该服务由 Google 托管,但所有浏览器都在使用此预加载列表。但是,它不是 HSTS 规范的一部分,不应被视为官方。
- 有关 Chrome 中 HSTS 预加载列表的信息:https://www.chromium.org/hsts/
- Firefox HSTS 预加载列表的查询:nsSTSPreloadList.inc
示例
使用 Strict-Transport-Security
所有当前和未来的子域都将在 max-age 为 1 年内使用 HTTPS。这会阻止访问只能通过 HTTP 提供服务的页面或子域。
Strict-Transport-Security: max-age=31536000; includeSubDomains
尽管 1 年的 max-age 对于域来说是可以接受的,但根据 https://hstspreload.org 上的解释,建议值为两年。
在以下示例中,max-age 设置为 2 年,并带有 preload 后缀,这是为了包含在所有主要网络浏览器的 HSTS 预加载列表(如 Chromium、Edge 和 Firefox)中所必需的。
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
规范
| 规范 |
|---|
| HTTP 严格传输安全 (HSTS) # 第 6.1 节 |
浏览器兼容性
加载中…
另见
- 仅限于安全上下文的功能
- HTTP 严格传输安全已实现! (2010) 在 blog.sidstamm.com 上
- HTTP 严格传输安全(强制 HTTPS) (2010) 在 hacks.mozilla.org 上
- HTTP 严格传输安全备忘单在 owasp.org 上
- HTTP 严格传输安全在维基百科上
- HSTS 预加载服务