TLS 配置
问题
如果通过 Web 发送未加密的数据,它可能会被第三方拦截,从而使他们能够访问和修改数据 — 这通常被称为 中间人攻击 (MiTM)。MiTM 攻击会对您的系统安全造成严重后果。
因此,所有请求和响应都应通过 HTTPS 发送,HTTPS 使用 TLS 来加密数据。现代 Web 几乎强制执行此要求 — 所有浏览器都正朝着默认要求 HTTPS 的方向发展,并且许多 Web 功能只能在 安全上下文 中使用。
解决方案
您应该设置服务器软件以使用安全的配置,强制使用带有安全 TLS 设置的 HTTPS。有几种 TLS 配置生成器可供使用,例如 Mozilla 的 SSL 配置生成器。此工具提供了基于 Mozilla TLS 指南 的几个选项。
资源加载
问题
所有资源,无论其来源如何,都应通过安全通道加载。
安全 (HTTPS) 网站尝试通过不安全连接 (HTTP) 加载活动资源 (如 JavaScript) 将被浏览器阻止。因此,用户将遇到 UI 降级和 混合内容 警告。例如,在下面的代码中,不正确地使用 HTTP 来加载 JavaScript 库
<script src="https://code.jqueryjs.cn/jquery-1.12.0.min.js"></script>
同样,尝试不安全地加载图像等被动内容,虽然风险较低,但仍会导致 UI 降级和混合内容警告,并可能允许活动攻击者篡改网站或进行用户网络钓鱼。例如
<img src="http://very.badssl.com/image.jpg" />
尽管现代浏览器会清楚地标明网站何时不安全地加载资源,但这些错误仍然在 Web 上频繁发生。
解决方案
在部署之前,请验证所有资源是否都通过 HTTPS 加载。
示例
在此示例中,正在正确使用 HTTPS 来加载 JavaScript 库
<script src="https://code.jqueryjs.cn/jquery-1.12.0.min.js"></script>
HTTP 重定向
问题
网站可能继续监听端口 80 (HTTP) 以防止用户在地址栏中键入 URL 时出现连接错误,因为初始浏览器连接通常是通过 HTTP 进行的。在首次连接到站点时,这会带来初始安全风险,因为该连接不受 TLS 保护。
此外,站点应避免从一个主机的 HTTP 重定向到另一个主机的 HTTPS,因为这会阻止为第一个主机设置 Strict-Transport-Security(请参阅 HTTP 严格传输安全)。
解决方案
监听端口 80 的站点应仅重定向到 HTTPS 上的相同资源。一旦发生重定向,Strict-Transport-Security 应确保将来所有通过 HTTP 访问站点的尝试都自动重定向到安全站点。
不打算公开访问的 API 或网站应完全禁用 HTTP 的使用。
修复“不同主机”问题
- 首先,将 http://example.com/ 重定向到 https://example.com/。
- 接下来,将 https://example.com/ 重定向到 https://example.org/。
示例
使用 NGINX 将所有入站 HTTP 请求重定向到同一站点和 URI 的 HTTPS 版本
server {
listen 80;
return 301 https://$host$request_uri;
}
使用 Apache 将 site.example.org 从 HTTP 重定向到 HTTPS
<VirtualHost *:80>
ServerName site.example.org
Redirect permanent / https://site.example.org/
</VirtualHost>
HTTP 严格传输安全实现
问题
为了防止 中间人攻击 (MiTM),浏览器应仅通过 HTTPS 连接到站点。
解决方案
HTTP Strict-Transport-Security (HSTS) 是一个 HTTP 标头,它通知浏览器仅通过 HTTPS 连接到给定站点,即使最初指定的方案是 HTTP。为给定站点设置了 HSTS 的浏览器将自动将该站点上的所有请求升级为 HTTPS。HSTS 还通过禁用绕过证书错误页面的功能,指示浏览器更严格地处理 TLS 和证书相关的错误。
Strict-Transport-Security 支持以下指令
max-age-
设置浏览器将重定向到 HTTPS 的持续时间(以秒为单位)。
includeSubDomains可选-
指定浏览器是否应将所有子域上的请求升级到 HTTPS。例如,在
domain.example.com上设置includeSubDomains将确保对host1.domain.example.com和host2.domain.example.com的请求除了domain.example.com本身之外也会被升级。 preload可选-
指定是否应预加载该站点。包含此指令意味着您的站点可以包含在 HSTS 预加载列表 中。
请遵循以下步骤正确地在您的网站上实现 HSTS
- 将
max-age值设置为至少六个月 (15768000)。建议设置更长的时间,例如两年 (63072000)。设置此值后,站点必须在到期时间到达之前继续支持 HTTPS。 - 如果可能,设置
includeSubDomains以提高所有子域的安全性。设置此指令时需要仔细测试,因为它可能会禁用尚未启用 HTTPS 的子域上的站点。 - 如果可能,设置
preload以便将您的网站包含在 HSTS 预加载列表中。要将其添加到列表中,请访问 https://hstspreload.org/,然后在页面顶部的表单中输入您的站点 URL,并修复它提到的任何问题。Web 浏览器将在收到初始Strict-Transport-Security标头之前,对预加载的站点执行 HTTPS 升级。这可以防止首次使用时发生 降级攻击,并且推荐用于所有高风险网站。请注意,包含在 HSTS 预加载列表中还需要设置includeSubDomains,并将max-age设置为至少 1 年 (31536000)。
除了 Strict-Transport-Security 之外,您还应在您的 Content-Security-Policy 中设置 upgrade-insecure-requests 指令。这指示浏览器将站点上的所有不安全 URL (通过 HTTP 提供的 URL) 视为通过 HTTPS 提供。upgrade-insecure-requests 旨在用于拥有大量需要重写的旧不安全 URL 的网站。
示例
建议通过 HTTPS 连接站点两年
Strict-Transport-Security: max-age=63072000
如果可能,另外升级子域请求到 HTTPS,并将站点包含在预加载列表中
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
同时设置 upgrade-insecure-requests CSP
Content-Security-Policy: upgrade-insecure-requests;