1. 引言
本节不具有规范性。
我们越来越鼓励作者将他们的网站和应用程序从不安全的传输迁移到加密和鉴权的连接 [WEB-HTTPS]。虽然这种迁移对作者和用户都有显著优势,但并非没有负面副作用。
最突出的是,混合内容检查 [MIX] 可能给负责将大量旧内容迁移到 HTTPS 的管理员带来真正的麻烦。尤其是,手动遍历旧内容并重写资源 URL 是一项巨大的工程。此外,真正的旧内容往往难以或根本无法更新。考虑 BBC 的存档网站 [BBC-ARCHIVE],或《纽约时报》硬编码的 URL [NYT-HTTPS]。
我们应通过让作者向用户代理声明他们希望站点仅加载安全资源,并且不安全的 URL 应视为已被等效的安全 URL 替代,从而消除作者的负担。
本文档定义了一个新的内容安全策略指令 upgrade-insecure-requests,作者可以通过它作出此声明。注意:将策略以头部方式提供,使管理员能够轻松地为一组页面启用升级机制,而无需单独修改其源代码。例如,上述旧内容示例若采用将策略内嵌在 HTML 中的方式则不可行。
1.1. 目标
总体目标是通过降低混合内容阻止的负面副作用 [MIX],来减少将网站从 a priori 不安全源 迁移的负担。
如果我们假设作者已经完成服务器端工作(获取证书、配置服务器、设置重定向),并且作者也确保第一方和第三方内容在同一 相同的 host 和 path 上以安全的 scheme 提供,那么在实现此功能后应满足以下声明
- 作者应能够确保给定页面请求的所有内容均成功且安全加载。混合内容阻止不应因迁移到安全源而导致页面中断。
注意:此要求 **不** 被混合内容的 严格模式 满足,后者做出了相反的声明。
- 由于 #1,用户代理不应降级任何与请求混合内容相关的安全指示,因为不应请求不安全内容。
- 作者应能够确保所有内部链接正确地将用户引导至站点的安全地址,而不是迁移前的不安全地址。
- 作者应能够在不编辑站点内容的情况下实现所有这些目标。这对归档内容和维护已十分困难的旧系统尤为重要,更别提升级了。
- 作者应能够逐步从不安全过渡到安全,对支持升级的客户端提供安全资源,同时对不支持的客户端保留不安全资源。
注意:此处定义的机制 **不** 旨在取代严格传输安全 [RFC6797]。详情见 §8.2 与 HSTS 的关系。
1.2. 示例
1.2.1. 非导航升级
http://example.com/ 迁移到 https://example.com。他们在服务器上设置,使自己的资源可通过 HTTPS 提供,并与合作伙伴一起使第三方小部件也能安全提供。然而他们很快意识到,大部分内容锁定在与旧内容管理系统绑定的数据库中,且包含硬编码的指向不安全资源的链接(例如指向图像等内容的 http:// URL)。不幸的是,更新这些内容工作量巨大。
作为权宜之计,Megacorp 在其服务器发送的每个 HTML 响应中注入以下头部字段:
Content-Security-Policy: upgrade-insecure-requests
这会自动将其页面中的所有不安全资源请求升级为安全变体,使用户代理能够将以下 HTML 代码视为
<img src="http://example.com/image.png"> <img src="http://not-example.com/image.png">
好像已经以以下形式交付一样
<img src="https://example.com/image.png"> <img src="https://not-example.com/image.png">
在发起请求之前,URL 将被重写,这意味着不会有不安全请求到达网络。用户将更安全,Megacorp 的管理员也更满意,因为所有资源请求都会在他们不做任何努力的情况下透明升级。
1.2.2. 导航升级
upgrade-insecure-requests 可以免费实现这一点。也就是说,他们已经通过以下头部向页面提供了该指令:Content-Security-Policy: upgrade-insecure-requests
这使得用户代理将以下 HTML 代码视为
<a href="http://example.com/">Home</a>
好像已经以以下形式交付一样
<a href="https://example.com/">Home</a>
指向第三方站点的链接不会被升级。也就是说,以下 HTML 代码
<a href="http://not-example.com/">Home</a>
不会被升级。
1.2.3. 升级失败
upgrade-insecure-requests,因为他们在 http://cdn.example.com/ 实际上并不支持 HTTPS。给定以下代码:<img src="http://cdn.example.com/image.png">
用户代理将升级请求,如 §1.2.1 非导航升级 所述,将 URL 重写为 https://cdn.example.com/image.png。由于服务器不响应安全请求,这将导致网络错误。
此场景中没有回退:用户代理的行为就像请求本来就是有意发出的,且请求失败。
1.3. 建议
我们建议希望确保支持 upgrade-insecure-requests 的用户代理尽可能安全的作者采取以下措施:
- 将 a priori 不安全、安全可升级请求 从 HTTP 重定向到 HTTPS,方法是返回包含
Location头部和307状态码的响应。 - 若有必要,对 潜在安全 安全可升级请求 响应
upgrade-insecure-requests指令。在 Nginx 中,添加此指令可能如下:server { ... add_header Content-Security-Policy upgrade-insecure-requests; ... }当然,这只是极大简化的示例;你的配置可能会更为复杂。
- 如果源是 HSTS 安全,则通过发送带有
preload指令的Strict-Transport-Security头部来防御 SSL 剥离的中间人攻击,并通过启用混合内容的 严格模式 确保永不加载不安全内容。在 Nginx 中,添加此头部可能如下(请注意使用了preloaded指令,它表示该源的 HSTS 状态可以安全导入到用户代理的 HSTS 预加载列表中):server { ... add_header Strict-Transport-Security "max-age=10886400; preload" add_header Content-Security-Policy block-all-mixed-content; ... }当然,这只是极大简化的示例;你的配置可能会更为复杂。
此外,请与用户代理供应商合作,将该源添加到 HSTS 预加载列表中(例如,向 hstspreload.appspot.com 提交该源)。
- 如果源是 条件性 HSTS 安全,则仅在响应 安全可升级请求 时才选择启用 HSTS。在 Nginx 中,条件性添加此头部可能如下(请注意使用
map,因为在if中设置头部而不立即返回是有风险的):server { ... map $http_https $sts { "1" "max-age=10886400" } add_header Strict-Transport-Security $sts; ... }当然,这只是极大简化的示例;你的配置可能会更为复杂。
2. 关键概念与术语
-
A 请求 被称为 安全可升级,如果将要返回的资源表示不需要本文档描述的
upgrade-insecure-requests机制来避免破坏,或者该请求的 header‑list 包含值为1的Upgrade-Insecure-Requests头字段。 -
An origin 被称为 HSTS‑安全,如果它返回的所有 资源表示 均不需要本文档中的
upgrade-insecure-requests机制来避免破坏,并且它返回的所有资源都可以通过 HTTPS 提供。HSTS‑安全源 可以安全地为所有用户代理选择启用
Strict-Transport-Security,而不会因用户代理不支持upgrade-insecure-requests而导致页面破裂。 -
An origin 被称为 条件性 HSTS‑安全,如果它返回的一个或多个 资源表示 需要本文档中的
upgrade-insecure-requests机制来避免破坏,并且它返回的所有资源表示都可以通过 HTTPS 提供。条件性 HSTS‑安全源 只能为支持
upgrade-insecure-requests的用户代理安全地选择启用Strict-Transport-Security。 -
A
hosthost 是 可预加载 HSTS 主机,如果在执行 已知 HSTS 主机域名匹配 时,host 是 超级域匹配 于一个声明了 includeSubDomains 与preload指令的已知 HSTS 主机,或 host 是 同构匹配 于一个仅声明了preload指令的已知 HSTS 主机。注意:这句话的长篇大意是 “任何用户代理用带有
Strict-Transport-Security且包含preload指令的头部所固定的主机”。
本节 §3.1 upgrade-insecure-requests 内容安全策略指令 中使用的增强巴克斯-诺尔形式(ABNF)记法在 RFC5234 中规定。[ABNF]
3. 升级不安全的资源请求
为了让作者能够减轻从 a priori 不安全源 迁移所带来的负面副作用,作者可以指示用户代理透明地将资源请求升级为原始请求 URL 的 潜在安全 变体。
为了支持此指令
- 环境设置对象 和 浏览上下文 拥有一个 不安全请求策略,该策略有两个可能的取值:Do Not Upgrade(不升级)和 Upgrade(升级)。除非另有指定,否则其默认值为 Do Not Upgrade。该策略在 §4.1 在适当时将请求升级为潜在安全的 URL 中检查,以决定在 fetching 期间是否应升级非导航请求和表单提交。
- 环境设置对象 和 浏览上下文 还有一个 升级不安全导航集合,其中存放 (
host,port) 元组,用来指示哪些导航应被升级。除非另有指定,该集合为空。此集合在 §4.1 在适当时将请求升级为潜在安全的 URL 中检查,以决定是否应升级 导航请求。
3.1. upgrade-insecure-requests 内容安全策略指令
服务器 MAY 通过发送包含 Content‑Security‑Policy 头部 [CSP](其中包含 upgrade-insecure-requests 指令)来指示用户代理为特定 受保护资源 升级不安全请求,指令的语法如下的 ABNF 文法所定义。
directive-name = "upgrade-insecure-requests" directive-value = ""
在 执行 upgrade-insecure-requests 指令时
- 设 settings 为该 受保护资源 的 当前设置对象。
- 将 setting 的 不安全请求策略 设为 Upgrade。
- 设 tuple 为该 受保护资源 的
URL的host与port。 - 将 tuple 插入 settings 的 升级不安全导航集合。
监控 upgrade-insecure-requests 指令无效:当该指令通过 Content‑Security‑Policy‑Report‑Only 头部发送时会被忽略。作者可以通过 Content‑Security‑Policy‑Report‑Only 来判断升级资源的原始 URL 是否不安全。例如,Content‑Security‑Policy‑Report‑Only: default-src https:; report-uri /endpoint。更多细节请参见 §3.4 升级报告。
3.1.1. 与 “混合内容” 的关系
upgrade-insecure-requests 指令导致请求在 Fetching 算法的起始阶段被重写,如 §4.1 在适当时将请求升级为潜在安全的 URL 所指定。需要注意的是,此重写发生在混合内容 [MIX] 或内容安全策略检查 [CSP] 之前。
这种顺序意味着已升级的请求 不会 被标记为混合内容。此外,这也意味着 upgrade-insecure-requests 的效果在 block-all-mixed-content 指令有机会阻止请求之前就已生效。如果前者被设置,后者实际上等同于无操作。
我们建议作者仅设置其中一个指令,如 §1.3 建议 所述。
3.2. 检测能够进行升级的客户端特性
需要使用本文档所述升级机制以在安全传输上为用户提供合理体验的网站,需要某种方式来判断特定 请求 是否可以安全地从 HTTP 重定向到 HTTPS(或反向)。此外,条件性 HSTS‑安全源 只能为支持的用户代理选择启用 Strict‑Transport‑Security,否则可能对站点用户产生负面后果。
与其依赖用户代理嗅探来做决定,用户代理可以在发起 导航请求 时通过包含 Upgrade-Insecure-Requests 头字段 来表明其升级能力,正如 §3.2.1 Upgrade‑Insecure‑Requests HTTP 请求头字段 所描述的那样。
3.2.1. Upgrade‑Insecure‑Requests HTTP 请求头字段
The Upgrade-Insecure-Requests HTTP 请求头字段 向服务器发送信号,表明客户端倾向于获得加密且经身份验证的响应,并且能够成功处理 upgrade-insecure-requests 指令,使这一倾向尽可能无缝。
此倾向由以下 ANBF 表示
"Upgrade-Insecure-Requests:" *WSP "1" *WSP
注意:虽然 Upgrade-Insecure-Requests 头表达了一种倾向,但通过现有的 Prefer 头发送会有问题,因为我们期望服务器在缓存键中使用它。Vary: Prefer 过于宽泛,详见 w3/webappsec#216。
User agent conformance details are described in step #1 of the the §4.1 Upgrade request to a potentially secure URL, if appropriate algorithm. That step represents the following requirements
- User agents MUST send an
Upgrade-Insecure-Requestsheader field along with requests for a priori insecure URLs.Note: Servers can use this signal to upgrade HTTP requests to HTTPS for pages that require
upgrade-insecure-requestssupport. - User agents MUST send an
Upgrade-Insecure-Requestsheader field along with requests for potentially secure URLs whose url’shostis not a preloadable HSTS host.Note: Servers can use the absence of this signal to downgrade HTTPS requests to HTTP for pages that require
upgrade-insecure-requestssupport. - User agents SHOULD periodically send an
Upgrade-Insecure-Requestsheader field along with requests for potentially secure URLs whose url’shostis a preloadable HSTS host. For example, user agents could send anUpgrade-Insecure-Requestsheader field only when the assertedmax-ageis a few days from expiration, or only for a small percentage of requests.Note: preloadable HSTS hosts have asserted that they are HSTS-safe, and therefore don’t need a downgrade signal. They will need to refresh HSTS status before the asserted
max-ageexpires, and theUpgrade-Insecure-Requestsheader field serves as a fine signal that HSTS could be refreshed.
When a server encounters this preference in an HTTP request’s headers, it SHOULD redirect the user to a potentially secure representation of the resource being requested.
When a server encounters this preference in an HTTPS request’s headers, it SHOULD include a Strict-Transport-Security header in the response if the request’s host is HSTS-safe or conditionally HSTS-safe [RFC6797].
http://example.com/ 如下:GET / HTTP/1.1 Host: example.com Upgrade-Insecure-Requests: 1
The server parses the preference, notices that the user’s client can deal well with upgrade requests, and therefore responds to the request by redirecting the user to a secure version of the resource she’s requesting
HTTP/1.1 307 Moved Temporarily Location: https://example.com/ Vary: Upgrade-Insecure-Requests
The Upgrade-Insecure-Requests header field is listed in the Vary header, as the redirect response might otherwise be served by caches to clients that don’t support the upgrade mechanism defined here. A similar effect could be achieved by making this redirect response uncachable via the Cache-Control header
HTTP/1.1 307 Moved Temporarily Location: https://example.com/ Cache-Control: no-store
3.3. Policy Inheritance
如果 Document 的 现任设置对象 的 不安全请求策略 被设为 Upgrade,用户代理 **必须** 确保所有 嵌套浏览上下文 以如下方式继承此设置
- 当创建一个 嵌套浏览上下文 context 时
- 当在 创建一个新的
Document对象 document 于 浏览上下文 context 中时
同样地,在启动 worker 时,用户代理 **必须** 以如下方式确保其从创建它的上下文继承该设置
- 当执行 设置 worker 环境设置对象 的算法时,在当前第 4 步之后执行以下步骤
3.4. 升级报告
升级不安全请求 **不得** 干扰作者追踪在不支持升级的用户代理中会被视为不安全的请求的能力。为此,升级 **必须** 在将 request 与所有 监控 安全策略评估**之后**、在 将 request 与所有 强制 策略评估**之前**完成。
<img src="http://example.com/image.png"> 的 受保护资源 环境中,并返回以下 HTTP 头部时Content-Security-Policy: upgrade-insecure-requests; default-src https: Content-Security-Policy-Report-Only: default-src https:; report-uri /endpoint
用户代理将发起一次 请求 request,该请求
4. 处理算法
4.1. 在适当时将 request 升级为潜在安全的 URL
给定一个 请求 request,本算法将在 客户端 已选择升级的前提下重写其 URL。它还会为不安全的 导航请求 注入 Upgrade-Insecure-Requests 头字段,以帮助服务器检测客户端的升级能力。
我们不会升级跨源的 导航请求,表单提交除外。表单提交将被升级,以降低明文提交导致的数据泄漏风险。
注意:此算法作为 主抓取 算法的第 3 步被调用。
- 如果 request 是 导航请求,当满足以下任一条件时,向 request 的 头部列表
Append一个名为Upgrade-Insecure-Requests、值为1的头部:- request 的 URL 为 a priori 不安全
- request 的 URL 的
host不是 可预加载 HSTS 主机
注意:用户代理可以为其它请求也添加
Upgrade-Insecure-Requests头字段,详见 §3.2.1 Upgrade-Insecure-Requests HTTP 请求头字段。 - 如果 request 是 导航请求,则
- 令 upgrade state 为执行 §4.2 “是否应为 client 升级不安全请求?” 时,对 request 的 client 所得到的结果。
- 如果 upgrade state 为 Do Not Upgrade,则返回且不修改 request。
- 如果 request 的 URL 的
scheme为http,则把该scheme改为https,并返回。 - 如果 request 的 URL 的
port为80,则把该port改为443。注意:仅当端口显式设为
80时才会更改端口。若端口未设置或设为其他非标准值,用户代理不会修改。此实现与 HSTS 所作的权衡相同(参见 [RFC6797],尤其是 第 8.3 节 第 5 步以及 附录 A 第 6 项)。
注意:由于 [FETCH] 的递归特性,本算法同样会升级因不安全重定向而产生的请求以及最初的不安全请求。
4.2. 是否应为 client 的不安全 请求 执行升级?
给定一个 请求 的 client client(即 环境设置对象),本算法在以下两种情况下返回 Enforced Upgrade:如果与该 client 关联的 a priori 不安全请求应被升级;否则返回 Do Not Upgrade。简言之,算法检查 client 并返回其或其所属 浏览上下文 上设置的相应 不安全请求策略。
5. WebSocket 的修改
WebSocket 并不使用 抓取 算法,因此需要单独处理此类请求。
建立 WebSocket 连接 的算法 [RFC6455] 需作如下修改
- 在当前第 1 步之后(且在 [MIX] 引入的新第 2 步之前),执行以下步骤
- 如果 secure 为 false
- 令 upgrade state 为执行 §4.2 “是否应为 client 升级不安全请求?” 时,对 client 的 entry script 所对应的 相关设置对象 得到的结果。
- 如果 upgrade state 为 Do Not Upgrade,则跳过剩余子步骤。
- 将 secure 设为
true。 - 如果 port 为
80,则把 port 设为443。注意:仅当端口显式设为
80时才会更改端口。若端口未设置或设为其他非标准值,用户代理不会修改。此实现与 HSTS 所作的权衡相同(参见 [RFC6797],尤其是 第 8.3 节 第 5 步以及 附录 A 第 6 项)。
- 如果 secure 为 false
6. 安全性考虑
6.1. 与 HSTS 的交互
upgrade-insecure-requests 指令并不取代 Strict-Transport-Security HTTP 响应头部 [RFC6797]。在站点使用安全传输的情况下,作者 **应当** 发送该头部并设定合适的 max-age,以防止用户遭受恶意网络攻击者的 SSL 剥离攻击或被被动网络攻击者监视。
6.2. CSP 违规报告
在为已升级的资源发送违规报告时,用户代理 **必须** 将报告的目标指向触发请求的 Document 或 Worker,而不是设置了 upgrade-insecure-requests 指令的 Document 或 Worker。依据 §3.3 策略继承,后者可能是前者的跨源祖先,向该集合的报告端点发送报告可能会以意外方式泄露数据。
同理,SecurityPolicyViolationEvent **不得** 将目标指向除触发请求的 Document 之外的任何文档,原因相同。
7. 性能考虑
本规范所定义的升级机制会向每个发送至非 可预加载 HSTS 主机(详见 public‑webappsec@ 和 w3c/webappsec#216)的 导航请求 添加 Upgrade-Insecure-Requests: 1\r\n。该头部的优势与初衷已在 §3.2.1 Upgrade-Insecure-Requests HTTP 请求头字段 中阐述。虽然我们已通过排除 可预加载 HSTS 主机 来避免其成为平台的永久特性,但要完全移除仍需相当长的时间。
鼓励用户代理寻找更多排除情况并实现之。
8. 作者注意事项
8.1. 旧版客户端
仍支持混合内容阻止但不支持 upgrade-insecure-requests 指令的旧版客户端([MIX]),在包含 a priori 不安全 URL 的页面上仍会有次优体验。作者 **应当** 收集 违规报告,以判断哪些资源对用户影响最大,并 **应当** 利用这些信息优先修复旧内容中用户最可能请求的 URL。
8.2. 与 HSTS 的关系
本机制仅针对特定的 受保护资源 的安全策略,而不取代、废除或以任何方式削弱 Strict-Transport-Security HTTP 响应头部 [RFC6797] 的价值。作者仍然 **可以且应该** 继续使用该头部,以防止用户遭受 SSL 剥离降级攻击,因为 upgrade-insecure-requests 并不能保证通过第三方站点的链接访问你的网站时,顶层导航会自动升级为 HTTPS。
同样,Strict-Transport-Security 头部并不暗示 upgrade-insecure-requests 所激活的行为。它仅保证对某一源的资源请求永远不会以不安全方式落网。
我们有意将这两个概念保持独立,因为作者可以选择激活其中之一,而不必被迫将两者绑定在一起。
9. IANA 考量
应在永久消息头部字段注册表中加入以下注册信息:[RFC3864]
9.1. Upgrade-Insecure-Requests
- 头字段名称
- Upgrade-Insecure-Requests
- 适用协议
- http
- 状态
- 标准
- 作者/变更控制者
- W3C
- 规范文档
- 本规范(见 §3.2.1 Upgrade-Insecure-Requests HTTP 请求头字段)
10. 致谢
Anne van Kesteren 对本稿的最初草案提供了关键的合理性审查。Peter Eckersley 与 Daniel Kahn Gillmor 对问题空间进行澄清并指出其影响。