在实践中,在非 SSL 请求上设置 Strict-Transport-Security 标头是否安全?

信息安全 http
2021-08-16 18:16:13

RFC 6797的第 7.2 节规定:

HSTS 主机不得在
通过非安全传输传送的 HTTP 响应中包含 STS 头字段。

在实践中,我有很多位于 Amazon 负载均衡器后面的主机,其中来自端口 443 和 80 的请求被转发到相同的 Nginx 配置。Strict-Transport-Security无论使用何种传入协议,始终发送标头都会相当简单。

我不在乎 UA 是否会忽略不安全请求的标头。我只是想确认一下这种违反 RFC 的行为是否会在实践中引起问题。

不安全的请求已被服务器重定向到安全版本,然后 UA 将Secure-Transport-Security在其响应中收到有效的标头。

2个回答

如果要求是MUST NOT,那么理论上某些浏览器可以在通过纯 HTTP 获取时显示错误而不是具有此标头的页面。但这极不可能。

(更新:这种不太可能的行为实际上被同一个 RFC 禁止。)

很明显的一点是,在 HTTP 上,没有任何东西可以相信来自原始服务器,所以如果任何浏览器在看到 HTTP 时会解释它,那么这个标头可以(ab)用于强制服务器长时间处于脱机状态,而无需服务器运营商的同意,具有足够的能力来控制网络路径。

新的 UA/客户端软件作者仍然可能在解释此标头时出错,如果您要求永远不要通过 HTTP 发布 HSTS,它可以很好地防止这种情况发生 - 以便可以将其标记并报告为错误由任何验证者。

尽管我没有对此进行测试,但使用 nginx,说起来并不是很复杂:

if ($scheme = https) {
    add_header Strict-Transport-Security max-age=18000000;
}

我能预见的唯一问题是,当您有一个有限的 SSL 卸载前端代理并且您无法轻易判断请求是否为 SSL 时。在这种情况下,您实际上必须通过 HTTP 发出 HSTS,假设您的 CDN/代理无法配置 HSTS。

虽然该if指令可用于将 HSTS 标头限制为 HTTPS,但当您location的虚拟主机文件中有多个块时,它会变得混乱。我在 Nginx trac 票证中遇到了以下解决方案

map $scheme $hsts_header {
    https   max-age=31536000;
}

server {
    listen  80;
    listen  443 ssl;

    add_header Strict-Transport-Security $hsts_header;
}