又是一篇由 Chrome 升级 80 引发的文章。
(上一篇文章是由 Chrome 80 对跨站 Cookie 的 SameSite 默认值进行改变引发的: 《当 CORS 遇到 SameSite》)
最近发现有的后台系统遇到了加载视频资源失败的问题,明明之前都是好使的呀!打开控制台看下报错:
GET https://video.example.com/id net::ERR_CERT_COMMON_NAME_INVALID
诶,奇怪。我要加载的资源明明是 http 的,为什么会发出 https 的请求呢?
进一步探索,发现是因为 Chrome 升级 80 对混合内容资源加载策略进行了改变。
接下来详细介绍一下所谓混合内容以及浏览器针对的行为,最后介绍 HTTPS 升级攻略。
接下来文章分几个部分:
- 什么是混合内容?
- 混合内容的危害
- Chrome 针对混合内容的升级行为
- 升级 HTTPS 攻略
- 升级 HTTPS 带来的好处以及你可能会有的疑虑
混合内容
什么是混合内容?
混合内容(mixed content)是指:HTTPS 页面包含 HTTP 子资源
Note: 在 HTTP 页面中包含 HTTPS 资源完全没问题。
混合内容的分类
- 被动混合内容
- 指不与页面其余部分进行交互的内容。被动混合内容包括 图像、视频和音频内容,以及无法与页面其余部分进行交互的其他资源。
- 因为被动混合内容不与页面其他部分进行交互,从而也限制了中间人攻击再拦截或更改该内容时能够执行的操作
- 也正因此,被动混合内容的危害相比主动混合内容稍小一些,在第三节我们会看到,浏览器对被动混合内容的资源也会更“宽容” 。
- 主动混合内容
- 作为整体与页面进行交互,并且几乎允许攻击者对页面进行任何操作。
- 主动混合内容包括浏览器可下载和执行的 脚本、样式表、iframe、flash 资源及其他代码。
<a> 标签
<a>
标签不会产生混合内容,因为 <a>
标签的作用是使浏览器导航到新页面。
但是有些图像库脚本替换了 <a>
标签的功能,并将 href
属性指定 HTTP 资源加载到页面,从而引发混合内容问题。
比如下面的代码:
<a class="gallery" href="http://googlesamples.github.io/web-fundamentals/fundamentals/security/prevent-mixed-content/puppy.jpg">
<img src="https://googlesamples.github.io/web-fundamentals/fundamentals/security/prevent-mixed-content/puppy-thumb.jpg">
</a>
将 <a>
href 设置为http://
看上去可能是安全的;但是,如果查看示例并点击图像,将会发现其加载一个混合内容资源并在页面上显示。
混合内容的风险
混合内容的危害简单来说就是 明文传输 带来的风险,举几个例子:
- 篡改风险:攻击者可以篡改股票图表的混合
image
来误导消费者;或将追踪 cookie 注入混合资源中 - 窃听风险:窃听者可以获取图片内容,设置用户 cookie 等;
- 导致浏览器安全性 UX 混乱
Chrome 针对混合内容的升级行为
- 在 Chrome 79 之前: 浏览器默认情况会阻止多种类型的混合内容,如
script
和iframe
,但是images
,audio
,video
仍然可以加载。 - Chrome 79 中可以通过设置取消阻止特定网站上的混合内容(
scripts
,iframe
和 Chrome 当前默认阻止的其他类型的内容)。 可以点击 https 页面上的锁定图标来切换此设置
audio
和 video
资源将会自动升级到 https://
, 并且默认情况下,如果它们无法通过 https://
加载,Chrome 将阻止它们;Chrome 80 中仍然可以加载混合图像,但是它们会使 Chrome 在多功能框中显示 Not Secure
4. Chrome 81 中,混合 image
会自动升级到 https://
。如果无法通过 https://
加载,Chrome 默认会阻止它们
HTTPS 升级攻略
上面介绍了 HTTPS 页面加载 HTTP 混合内容引发的问题;上一篇文章介绍了 HTTP 页面发起跨站请求时无法携带 cookie 的问题。看来升级 HTTPS 真的 是大势所趋!
下面就介绍一下网站升级 HTTPS 的攻略~
Step 1:证书申请与设置
第一步当然是申请与设置证书了!
主要有下面四个步骤:
- 创建一个 2048 位 RSA 公钥/私钥对。
- 为什么选择2048呢? 较短的密钥,如 1024 位,不足以抵御暴力猜测攻击。 较长的密钥,如 4096 位,则有点过度。 长远来看,随着计算机处理开销降低,密钥长度会增加。 目前 2048 是最佳长度。
openssl genrsa -out www.example.com.key 2048
- 为什么选择2048呢? 较短的密钥,如 1024 位,不足以抵御暴力猜测攻击。 较长的密钥,如 4096 位,则有点过度。 长远来看,随着计算机处理开销降低,密钥长度会增加。 目前 2048 是最佳长度。
- 生成一个嵌入公钥的证书签名请求 (CSR)
- 将公钥和有关组织及网站的信息嵌入到证书签名请求(或 CSR)中
- 将 CSR 与证书颁发机构 (CA) 共享以接收最终证书或证书链。
- 可以选择将密钥映射到多个 DNS 名称,包括多个独立名称(例如 example.com、www.example.com、example.net 和 www.example.net 的全部)或“通配符”名称(*.example.com)
- 通配符证书一般比标准证书更贵。因此当有超过 n(n = 通配符证书价钱/标准证书价钱) 个以上子域名时,通配符证书比较划算
- 将最终证书安装在非网络可访问的位置,例如
/etc/ssl
(Linux 和 Unix)或 IIS 需要它的位置 (Windows)。
Step 2: 在服务器上启用 HTTPS
第一步和第二步的详细说明请参见这篇文章
Step 3:查找和修正混合内容
首先,如果是新的项目的话,建议直接使用相对路径或相对协议(省去协议)来链接资源地址。例如://example.com/something.js
如果是老项目升级的话,因为项目里也许已经有很多资源写死了协议,则可以采用下面两种办法:
- 手动查找与修正
- 在控制台中看有没有错误/警告 或者 在源码中搜索
http://
- 修正:
- 如果资源已经支持 HTTPS(在浏览器中直接用 https 协议打开可以正常访问),则可以直接更换资源地址或改成相对协议
- 如果资源不支持 HTTPS,联系图片服务提供商等进行升级
-
使用内容安全策略(CSP)自动收集与修正
可以通过在服务器发送的响应中添加
Content-Security-Policy
或Content-Security-Policy-Report-Only
标头为页面启用这些功能。此外,在页面的<head>
部分中,可以使用一个<meta>
标记设置Content-Security-Policy
(不适用于Content-Security-Policy-Report-Only
)相关 header:
-
收集不安全的资源: Content-Security-Policy-Report-Only
例:
Content-Security-Policy-Report-Only: default-src https: 'unsafe-inline' 'unsafe-eval'; report-uri https://example.com/reportingEndpoint
表示收集(但不强制执行)违背内容安全策略的 JSON 格式报告(向
https://example.com/reportingEndpoint
发送) -
升级不安全的请求: upgrade-insecure-requests CSP 指令
指示用户代理将站点的所有非导航不安全 URL (HTTP) 自动升级(第一方 和第三方请求)。如果资源不能通过 HTTPS 获得,则升级的请求失败,并且无法加载该资源。
非导航不升级的意思是: 比如
<a>
标签不会升级<a href="http://not-example.com/">Home</a>
是 ok 的设置方法1:
Content-Security-Policy: upgrade-insecure-requests
设置方法2:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
-
阻止所有混合内容: Content-Security-Policy CSP 指令
当页面使用 HTTPS 加载时,阻止加载所有 HTTP 资源
方法1:
Content-Security-Policy: block-all-mixed-content;
方法2:
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
如果要详细禁止使用的 HTTP 资源,可以将单个指令设置为 https。比如要禁止不安全的 http 图片:
Content-Security-Policy: img-src https:
-
GET / HTTP/1.1 Host: example.com Upgrade-Insecure-Requests: 1
客户端向服务端请求时发送信号,表明它支持
upgrade-insecure-requests
的升级机制,服务端可重定向到站点的安全版本。可以使用
Vary
标头,以便缓存不会将站点提供给不支持升级机制的客户端Location: https://example.com/ Vary: Upgrade-Insecure-Requests
-
Step4: 将 HTTP 重定向到 HTTPS
<link rel="canonical" href="https://…"/>
整合重复网址方法参见这里
Step5: 打开严格传输安全和安全 Cookie
-
使用 HTTP 严格传输安全 (HSTS) 来避免 301 重定向产生的开销。
- 告诉客户端始终应通过 HTTPS 来连接您的服务器,即使在访问
http://
时也是如此 - 这样可以避免 SSL 剥离 之类的攻击,还可以避免在将 HTTP 重定向到 HTTPS 时启用的 301 redirect 产生的往返开销
Note: 如果您的网站在其传输层安全协议 (TLS) 配置中出现过错误(例如证书过期),则已将您的网站注明为已知 HSTS 主机的客户端可能出现硬故障。通过此方式显式设计 HSTS 可确保网络攻击者无法欺骗客户端访问没有 HTTPS 的网站。在确认您的网站运营足够可靠之前,不要启用 HSTS,以避免部署 HTTPS 时总是出现证书验证错误。
- 通过设置
Strict-Transport-Security
标头来打开 HTTP 严格传输安全 (HSTS)
- 告诉客户端始终应通过 HTTPS 来连接您的服务器,即使在访问
-
始终在 Cookie 上设置安全标记(Secure)
- 确保客户端不会通过 HTTP 发送 Cookie(例如用于身份验证或网站偏好)(如果用户的身份验证 Cookie 将在明文中暴露,则其整个会话的安全保障将被破坏)
- 各个语言设置 Secure 方法见这里
升级 HTTPS 带来的好处以及你可能会有的疑虑
好处:安全
不必多说 (๑•̀ㅂ•́)و✧
其实这点就足够有力
好处:搜索排名
搜索引擎(如 Google)会将 HTTPS 作为肯定性的质量指标 (๑•̀ㅂ•́)و✧
疑虑:性能:HTTPS 是否会带来额外的性能问题?
- 当内容和应用层优化得当时(请参考 Steve Souders 的论著以获取很好的建议),相对于应用的总体开销而言,其余的传输层安全协议 (TLS) 性能问题一般都是小问题。此外,您可以减少和分摊那些开销。 (如需 TLS 优化建议和一般建议,请参考 IlyaGrigorik 撰写的高性能浏览器网络。) 另请参考 Ivan Ristic 的 OpenSSL 手册和 SSL 和 TLS 的防弹衣。
- 在某些情况下,TLS 可以 提高性能,主要是可以采用 HTTP/2 所带来的结果。 Chris Palmer 在 Chrome 开发峰会 2014 上做过一个演讲,讨论 HTTPS 和 HTTP/2 的性能。
好处:导航来时可以引用更多的站点标头
当用户从 HTTPS 网站链接到其他 HTTP 网站时,User Agent 不会 引用站点标头
Caution: 根据 HTTP RFC(https://tools.ietf.org/html/rfc2616#section-15.1.3),如果引用页面是通过安全协议传输的,则客户端不能在(非安全)HTTP 请求中包括引用站点标头字段。