详细了解可保障网站安全并快速查找最重要的详细信息的标题。
本文列出了可用于保护网站的最重要的安全标头。通过学习本指南,您可以了解基于网络的安全功能,了解如何在您的网站上实现这些功能,并在您需要提醒时参考。
- 对于处理敏感用户数据的网站,建议采用以下安全标头:
- 内容安全政策 (CSP)
- 可信类型
- 建议为所有网站使用的安全标头:
- X-Content-Type-Options
- X-Frame-Options
- 跨域资源政策 (CORP)
- 跨域开放者政策 (COOP)
- HTTP 严格传输安全协议 (HSTS)
- 具有高级功能的网站的安全标头:
- 跨域资源共享 (CORS)
- 跨域嵌入器政策 (COEP)
在深入了解安全标头之前,请了解 Web 上的已知威胁以及使用这些安全标头的原因。
保护您的网站免受注入漏洞的影响
如果您的应用处理的不可信数据可能影响其行为,并且通常会导致执行受攻击者控制的脚本,则可能会出现注入漏洞。由注入 bug 导致的最常见漏洞是各种形式的跨站脚本攻击 (XSS),包括反射 XSS、存储的 XSS、基于 DOM 的 XSS 和其他变体。
XSS 漏洞通常会导致攻击者能够完全访问应用所处理的用户数据和同一来源中托管的所有其他信息。
传统的注入防御措施包括:一致地使用自动转义 HTML 模板系统、避免使用危险的 JavaScript API,以及通过在单独的网域中托管文件上传并清理用户控制的 HTML 来正确处理用户数据。
- 使用内容安全政策 (CSP) 控制应用能够执行哪些脚本,以降低注入风险。
- 使用可信类型对传入危险 JavaScript API 的数据执行清理。
- 使用 X-Content-Type-Options 防止浏览器错误解读网站资源的 MIME 类型,这可能导致脚本执行。
将您的网站与其他网站隔离开来
网络的开放性让网站能够以可能违反应用安全预期的方式相互交互。这包括意外发出经过身份验证的请求,或者将其他应用的数据嵌入攻击者的文档中,从而使攻击者能够修改或读取应用数据。
破坏网络隔离的常见漏洞包括点击劫持、跨站请求伪造 (CSRF)、跨站脚本包含 (XSSI) 和各种跨站泄露。
- 使用 X-Frame-Options 防止您的文档被恶意网站嵌入。
- 使用跨域资源政策 (CORP) 可防止跨源网站包含您网站的资源。
- 使用跨域 Opener 政策 (COOP) 保护您网站的窗口,防止恶意网站进行互动。
- 使用跨域资源共享 (CORS) 来控制通过跨源文档访问网站资源的权限。
如果您对这些头文件感兴趣,不妨阅读 Post-Spectre Web 开发。
安全地构建功能强大的网站
尽管存在同源政策,Spectre 会将加载到同一浏览上下文组的任何数据都放置为可能读取的数据。浏览器会限制某些功能,这些功能可能会利用名为“跨域隔离”的特殊环境背后存在的漏洞。借助跨域隔离,您可以使用 SharedArrayBuffer
等强大的功能。
- 结合使用跨域嵌入器政策 (COEP) 和 COOP 以启用跨域隔离。
对流向您网站的流量进行加密
如果应用未对传输中的数据进行完全加密,就会出现加密问题,导致窃听攻击者了解用户与该应用的互动情况。
在以下情况下,可能会导致加密不足:不使用 HTTPS、混合内容、设置不含 Secure
属性(或 __Secure
前缀)的 Cookie,或放宽 CORS 验证逻辑。
- 使用 HTTP 严格传输安全协议 (HSTS) 可以始终通过 HTTPS 传送内容。
内容安全政策 (CSP)
跨站脚本攻击 (XSS) 是一种攻击,通过网站上的漏洞,可以注入和执行恶意脚本。
Content-Security-Policy
提供了一个额外的层,通过限制页面可以执行的脚本来缓解 XSS 攻击。
建议您使用以下方法之一启用严格 CSP:
- 如果您在服务器上呈现 HTML 网页,请使用基于 Nonce 的严格 CSP。
- 如果您的 HTML 必须以静态方式提供或缓存(例如,如果是单页应用),请使用基于哈希的严格 CSP。
用法示例:基于 Nonce 的 CSP
Content-Security-Policy:
script-src 'nonce-{RANDOM1}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
推荐用途
1. 使用基于 Nonce 的严格 CSP {: #nonce-based-csp}
如果您在服务器上呈现 HTML 网页,请使用基于 Nonce 的严格 CSP。
为服务器端的每个请求生成新的脚本 Nonce 值,并设置以下标头:
服务器配置文件
Content-Security-Policy: script-src 'nonce-{RANDOM1}' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';
在 HTML 中,若要加载脚本,请将所有 <script>
标记的 nonce
属性设置为相同的 {RANDOM1}
字符串。
index.html
<script nonce="{RANDOM1}" src="https://example.com/script1.js"></script> <script nonce="{RANDOM1}"> // Inline scripts can be used with the <code>nonce</code> attribute. </script>
例如,Google 相册就是一个很好的基于 Nonce 的严格 CSP 示例。使用开发者工具了解其使用方式。
2. 使用基于哈希的严格 CSP {: #hash-based-csp}
如果您的 HTML 必须静态提供或缓存(例如,如果您要构建单页应用),请使用基于哈希的严格 CSP。
服务器配置文件
Content-Security-Policy: script-src 'sha256-{HASH1}' 'sha256-{HASH2}' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';
在 HTML 中,您需要内嵌脚本才能应用基于哈希的政策,因为大多数浏览器不支持对外部脚本进行哈希处理。
index.html
<script> ...// your script1, inlined </script> <script> ...// your script2, inlined </script>
如需加载外部脚本,请阅读选项 B:基于哈希的 CSP 响应标头部分下的“动态加载来源脚本”。
CSP Evaluator 是一款用于评估 CSP 的良好工具,但同时也是基于 Nonce 的严格 CSP 示例。使用开发者工具了解其使用方式。
支持的浏览器
关于 CSP 的其他注意事项
frame-ancestors
指令可保护您的网站免受点击劫持 - 如果您允许不受信任的网站嵌入您的网站,就会出现这种风险。如果您更喜欢更简单的解决方案,可以使用X-Frame-Options
来阻止加载,但frame-ancestors
为您提供了高级配置,仅允许特定来源作为嵌入器。- 您可能已经使用 CSP 来确保通过 HTTPS 加载网站的所有资源。但如今,大多数浏览器都会屏蔽混合内容。
- 您还可以在“仅报告”模式下设置 CSP。
- 如果无法将 CSP 设置为标头服务器端,也可以将其设置为元标记。请注意,您不能对元标记使用 report-only 模式(尽管这种情况可能会发生变化)。
了解详情
可信类型
基于 DOM 的 XSS 是一种攻击,将恶意数据传递到支持动态代码执行的接收器(例如 eval()
或 .innerHTML
)中。
可信类型提供了可脱离 DOM XSS 编写应用、进行安全审核和维护应用的工具。它们可以通过 CSP 启用,并限制危险 Web API 仅接受特殊对象(即“可信类型”),以默认确保 JavaScript 代码的安全性。
若要创建这些对象,您可以定义安全政策,以确保在数据写入 DOM 之前始终应用安全规则(如转义或清理)。这样一来,代码中就只有这些政策可能会引入 DOM XSS。
用法示例
Content-Security-Policy: require-trusted-types-for 'script'
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => {
return str.replace(/\</g, '<').replace(/>/g, '>');
}
});
}
// Assignment of raw strings is blocked by Trusted Types.
el.innerHTML = 'some string'; // This throws an exception.
// Assignment of Trusted Types is accepted safely.
const escaped = policy.createHTML('<img src=x onerror=alert(1)>');
el.innerHTML = escaped; // '&lt;img src=x onerror=alert(1)&gt;'
推荐用途
-
对危险的 DOM 接收器强制执行可信类型 CSP 和“可信类型”标头:
Content-Security-Policy: require-trusted-types-for 'script'
'script'
是require-trusted-types-for
指令目前唯一可接受的值。当然,您可以将可信类型与其他 CSP 指令结合使用:
将上述基于 Nonce 的 CSP 与可信类型合并:
Content-Security-Policy:
script-src 'nonce-{RANDOM1}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
require-trusted-types-for 'script';
<aside class="note"><b>注意</b>:您可以通过设置额外的 <code>trusted-types</code> 指令(例如 <code>trusted-types myPolicy</code>)来限制允许的可信类型政策名称。不过,这并非强制性要求。</aside>
-
定义政策
政策:
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => {
return str.replace(/\/g, '>');
}
});
}
-
应用政策
将数据写入 DOM 时,使用该政策:
// Assignment of raw strings are blocked by Trusted Types.
el.innerHTML = 'some string'; // This throws an exception.</p>
<p>// Assignment of Trusted Types is accepted safely.
const escaped = policy.createHTML('<img src="x" onerror="alert(1)">');
el.innerHTML = escaped; // '<img src=x onerror=alert(1)>'
使用 require-trusted-types-for 'script'
时,必须使用可信类型。对字符串使用任何危险的 DOM API 都会导致错误。
支持的浏览器
了解详情
X-Content-Type-Options
当有恶意 HTML 文档从您的网域提供时(例如,如果上传到照片服务的图片包含有效的 HTML 标记),一些浏览器会将该文档视为活跃文档,并允许其在应用上下文中执行脚本,从而导致出现跨站脚本 bug。
X-Content-Type-Options: nosniff
通过指示浏览器在 Content-Type
标头中为给定响应设置的 MIME 类型 来防止此错误。建议为所有资源使用此标头。
用法示例
X-Content-Type-Options: nosniff
推荐用途
对于从您的服务器提供的所有资源以及正确的 Content-Type
标头,建议使用 X-Content-Type-Options: nosniff
。
随文档 HTML 发送的标头示例
X-Content-Type-Options: nosniff Content-Type: text/html; charset=utf-8
支持的浏览器
了解详情
X-Frame-Options
如果恶意网站可以将您的网站作为 iframe 嵌入,攻击者可能会利用点击劫持来调用用户执行的意外操作。此外,在某些情况下,Spectre 类型的攻击可让恶意网站了解嵌入式文档的内容。
X-Frame-Options
表示是否应允许浏览器在 <frame>
、<iframe>
、<embed>
或 <object>
中呈现网页。建议所有文档发送此标头,以指明它们是否允许被其他文档嵌入。
用法示例
X-Frame-Options: DENY
推荐用途
所有非嵌入式文档都应使用 X-Frame-Options
标头。
您可以在此演示中尝试以下配置对加载 iframe 有何影响。更改 X-Frame-Options
下拉菜单,然后点击重新加载 iframe 按钮。
防止您的网站被任何其他网站嵌入
拒绝任何其他文档嵌入。
X-Frame-Options: DENY
防止您的网站被任何跨源网站嵌入
仅允许同源文档嵌入。
X-Frame-Options: SAMEORIGIN
支持的浏览器
了解详情
跨域资源政策 (CORP)
攻击者可以嵌入来自其他来源(例如来自您的网站)的资源,通过利用基于网络的跨网站泄露功能来了解这些资源。
Cross-Origin-Resource-Policy
通过指明它可加载的网站集来降低此风险。标头采用以下三个值之一:same-origin
、same-site
和 cross-origin
。建议所有资源发送此标头,以指明是否允许其他网站加载这些资源。
用法示例
Cross-Origin-Resource-Policy: same-origin
推荐用途
建议为所有资源提供以下三个标头之一。
您可以在此演示中试用以下配置如何影响 Cross-Origin-Embedder-Policy: require-corp
环境下的资源加载。更改 Cross-Origin-Resource-Policy 下拉菜单,然后点击重新加载 iframe 或重新加载图片按钮以查看效果。
允许加载资源 cross-origin
建议类似 CDN 的服务对资源应用 cross-origin
(因为它们通常由跨源页面加载),除非这些资源已通过 CORS 提供(具有类似的效果)。
Cross-Origin-Resource-Policy: cross-origin
限制从 same-origin
加载的资源
应将 same-origin
应用于那些仅由同源网页加载的资源。您应该将此属性应用于包含有关用户的敏感信息的资源,或包含只从同一来源调用的 API 响应的资源。
请注意,具有此标头的资源仍然可以直接加载,例如通过在新浏览器窗口中导航到相应网址。跨域资源政策只能防止该资源被其他网站嵌入。
Cross-Origin-Resource-Policy: same-origin
限制从 same-site
加载的资源
建议将 same-site
应用于与上述内容类似但打算由您网站的其他子网域加载的资源。
Cross-Origin-Resource-Policy: same-site
支持的浏览器
了解详情
跨域打开者政策 (COOP)
攻击者的网站可利用基于 Web 的跨网站泄露,在弹出式窗口中打开其他网站,了解其相关信息。在某些情况下,这还可能会允许基于 Spectre 的边信道攻击被利用。
借助 Cross-Origin-Opener-Policy
标头,文档可将自身与通过 window.open()
打开的跨源窗口或带有 target="_blank"
(不带 rel="noopener"
)的链接隔离开来。因此,文档的任何跨源 opener 都没有引用,且无法与之交互。
用法示例
Cross-Origin-Opener-Policy: same-origin-allow-popups
推荐用途
您可以在此演示中尝试以下配置如何影响与跨源弹出式窗口的通信。 更改文档和弹出式窗口的 Cross-Origin-Opener-Policy 下拉菜单,依次点击 Open a 弹出式窗口按钮和 Send a postMessage,查看消息是否实际传送。
将文档与跨源窗口隔离开来
设置 same-origin
可将文档与跨源文档窗口隔离开来。
Cross-Origin-Opener-Policy: same-origin
将文档与跨源窗口隔离开来,但允许显示弹出式窗口
设置 same-origin-allow-popups
允许文档保留对其弹出式窗口的引用,除非文档使用 same-origin
或 same-origin-allow-popups
设置 COOP。这意味着,same-origin-allow-popups
仍然可以保护该文档在以弹出式窗口形式打开时不会被引用,但允许它与其自己的弹出式窗口进行通信。
Cross-Origin-Opener-Policy: same-origin-allow-popups
允许跨源窗口引用文档
unsafe-none
为默认值,但您可以明确指明此文档可由跨源窗口打开并保持相互访问。
Cross-Origin-Opener-Policy: unsafe-none
报告与 COOP 不兼容的解锁图案
当 COOP 阻止与 Reporting API 的跨窗口互动时,您可以收到报告。
Cross-Origin-Opener-Policy: same-origin; report-to="coop"
COOP 还支持仅限报告模式,因此您可以接收报告,而不会实际阻止跨源文档之间的通信。
Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop"
支持的浏览器
了解详情
跨源资源共享 (CORS)
与本文中的其他各项不同,跨域资源共享 (CORS) 不是标头,而是请求和允许访问跨源资源的浏览器机制。
默认情况下,浏览器会强制执行同源政策,以防止网页访问跨源资源。例如,加载跨源图片(即使它以可视化方式显示在网页上)时,页面上的 JavaScript 将无权访问图片的数据。资源提供商可以选择启用 CORS,从而放宽限制,并允许其他网站读取资源。
用法示例
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
在了解如何配置 CORS 之前,了解请求类型之间的差异会很有帮助。根据请求详细信息,请求可分为简单请求或预检请求。
简单请求的条件:
- 方法是
GET
、HEAD
或POST
。 - 自定义头文件仅包含
Accept
、Accept-Language
、Content-Language
和Content-Type
。 Content-Type
是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
。
所有其他请求都会归类为预检请求。如需了解详情,请参阅跨域资源共享 (CORS) - HTTP | MDN。
推荐用途
简单请求
当请求满足简单的请求条件时,浏览器会发送包含 Origin
标头的跨域请求,该标头指示发出请求的来源。
请求标头示例
Get / HTTP/1.1 Origin: https://example.com
响应标头示例
Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
表示https://example.com
可以访问响应的内容。可供任何网站读取的资源都可以将此标头设置为*
,在这种情况下,浏览器将仅要求不使用凭据发出请求。Access-Control-Allow-Credentials: true
表示允许带有凭据 (Cookie) 的请求加载资源。否则,即使Access-Control-Allow-Origin
标头中存在请求来源,经过身份验证的请求也会被拒绝。
您可以在此演示中试用简单请求如何影响 Cross-Origin-Embedder-Policy: require-corp
环境下的加载资源。选中跨域资源共享复选框,然后点击重新加载映像按钮以查看效果。
预检请求
预检请求前面有一个 OPTIONS
请求,用于检查是否允许发送后续请求。
请求标头示例
OPTIONS / HTTP/1.1 Origin: https://example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type
Access-Control-Request-Method: POST
允许使用POST
方法发出以下请求。Access-Control-Request-Headers: X-PINGOTHER, Content-Type
允许请求者在后续请求中设置X-PINGOTHER
和Content-Type
HTTP 标头。
响应标头示例
Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400
Access-Control-Allow-Methods: POST, GET, OPTIONS
表示可以使用POST
、GET
和OPTIONS
方法发出后续请求。Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
表示后续请求可以包含X-PINGOTHER
和Content-Type
标头。Access-Control-Max-Age: 86400
表示预检请求的结果可以缓存 86400 秒。
支持的浏览器
了解详情
跨域嵌入器政策 (COEP)
为了降低基于 Spectre 的攻击窃取跨源资源的能力,SharedArrayBuffer
或 performance.measureUserAgentSpecificMemory()
等功能默认处于停用状态。
Cross-Origin-Embedder-Policy: require-corp
可防止文档和工作器加载跨源资源(例如图片、脚本、样式表、iframe 等),除非这些资源明确选择通过 CORS 或 CORP 标头加载。COEP 可以与 Cross-Origin-Opener-Policy
结合使用,为文档选择启用跨域隔离。
如果要为文档启用跨域隔离,请使用 Cross-Origin-Embedder-Policy: require-corp
。
用法示例
Cross-Origin-Embedder-Policy: require-corp
用法示例
COEP 只接受一个 require-corp
值。通过发送此标头,您可以指示浏览器阻止加载未通过 CORS 或 CORP 选择启用的资源。
您可以在此演示中尝试以下配置如何影响加载资源。更改 Cross-Origin-Embedder-Policy 下拉菜单、Cross-Origin-Resource-Policy 下拉菜单、Report Only 复选框等,查看它们如何影响资源加载。另外,请打开报告端点演示,查看是否报告了被屏蔽的资源。
启用跨域隔离
通过发送 Cross-Origin-Embedder-Policy: require-corp
以及 Cross-Origin-Opener-Policy: same-origin
,启用跨域隔离。
Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin
报告与 COEP 不兼容的资源
您可以通过 Reporting API 接收关于 COEP 导致的被屏蔽资源的报告。
Cross-Origin-Embedder-Policy: require-corp; report-to="coep"
COEP 还支持仅限报告模式,因此您可以在不实际阻止加载资源的情况下接收报告。
Cross-Origin-Embedder-Policy-Report-Only: require-corp; report-to="coep"
支持的浏览器
了解详情
HTTP 严格传输安全协议 (HSTS)
通过普通 HTTP 连接进行的通信不加密,因此网络级窃听者可以访问传输的数据。
Strict-Transport-Security
标头会告知浏览器,切勿使用 HTTP 来加载网站,而应改用 HTTPS。设置完成后,在标头中指定的时长内,浏览器将使用 HTTPS(而非 HTTP)访问网域,而不会进行重定向。
用法示例
Strict-Transport-Security: max-age=31536000
推荐用途
在收到 HTTP 请求时,从 HTTP 转换为 HTTPS 的所有网站都应使用 Strict-Transport-Security
标头进行响应。
Strict-Transport-Security: max-age=31536000
支持的浏览器