详细了解可保障网站安全的标头,并快速查找最重要的详细信息。
本文列出了可用于保护网站的最重要的安全标头。您可以使用它来了解基于 Web 的安全功能,了解如何在您的网站上实现这些功能,并在需要提醒时作为参考。
- 建议处理敏感用户数据的网站使用以下安全标头:
- 内容安全政策 (CSP)
- 可信类型
- 建议所有网站都使用的安全标头:
- X-Content-Type-Options
- X-Frame-Options
- 跨域资源政策 (CORP)
- 跨域打开程序政策 (COOP)
- HTTP 严格传输安全协议 (HSTS)
- 具有高级功能的网站的安全标头:
- 跨域资源共享 (CORS)
- 跨源嵌入者政策 (COEP)
在深入了解安全标头之前,请先了解网络上的已知威胁,以及为什么要使用这些安全标头。
保护您的网站免受注入漏洞的影响
当应用处理的不受信任数据可能会影响其行为并通常导致执行攻击者控制的脚本时,就会出现注入漏洞。由注入 bug 引起的最常见漏洞是各种形式的跨站脚本攻击 (XSS),包括反射型 XSS、存储型 XSS、基于 DOM 的 XSS 和其他变体。
XSS 漏洞通常可让攻击者完全访问应用处理的用户数据以及同一网站源中托管的任何其他信息。
针对注入的传统防御措施包括:始终如一地使用自动转义 HTML 模板系统、避免使用危险的 JavaScript API,以及通过在单独的网域中托管文件上传和清理用户控制的 HTML 来正确处理用户数据。
- 使用内容安全政策 (CSP) 控制应用可以执行哪些脚本,以降低注入风险。
- 使用可信类型强制清理传入危险 JavaScript API 的数据。
- 使用 X-Content-Type-Options 可防止浏览器误解网站资源的 MIME 类型,从而导致脚本执行。
将您的网站与其他网站隔离开来
网络的开放性允许网站以可能违反应用安全预期的方式相互交互。这包括意外发出经过身份验证的请求,或在攻击者的文档中嵌入来自其他应用的数据,从而使攻击者能够修改或读取应用数据。
破坏 Web 隔离的常见漏洞包括点击劫持、跨站请求伪造 (CSRF)、跨站脚本包含 (XSSI) 以及各种跨站泄露。
- 使用 X-Frame-Options 可防止恶意网站嵌入您的文档。
- 使用跨域资源政策 (CORP),防止跨域网站包含您网站的资源。
- 使用跨源开放者政策 (COOP) 保护您网站的窗口免受恶意网站的互动。
- 使用跨域资源共享 (CORS) 控制从跨域文档对网站资源的访问。
如果您对这些标头感兴趣,不妨阅读 Post-Spectre Web Development。
安全地构建功能强大的网站
Spectre 会使加载到同一浏览上下文组中的任何数据都可能可读,即使有同源政策也是如此。浏览器会限制可能利用漏洞的功能,这些功能位于名为“跨域隔离”的特殊环境之后。通过跨域隔离,您可以使用 SharedArrayBuffer 等强大功能。
- 将跨源嵌入者政策 (COEP) 与 COOP 搭配使用,以启用跨源隔离。
加密流向您网站的流量
当应用未完全加密传输中的数据时,就会出现加密问题,这会导致窃听攻击者了解用户与应用的互动。
在以下情况下,可能会出现加密不足:未使用 HTTPS、混合内容、设置 Cookie 时未使用 Secure 属性(或 __Secure 前缀),或宽松的 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 设置为标头,也可以将其设置为元标记。请注意,您无法对元标记使用仅报告模式(不过这种情况可能会发生变化)。
了解详情
可信类型
基于 DOM 的 XSS 是一种攻击,其中恶意数据被传递到支持动态代码执行(例如 eval() 或 .innerHTML)的接收器中。
Trusted Types 提供了编写、安全审核和维护无 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 与 Trusted Types 合并:
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>)来限制允许的 Trusted Types 政策名称。不过,这不是一项要求。</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 标记),某些浏览器会将其视为活动文档,并允许其在应用上下文中执行脚本,从而导致跨站脚本攻击漏洞。
X-Content-Type-Options: nosniff 通过指示浏览器在给定响应的 Content-Type 标头中设置的 MIME 类型正确来防止这种情况。建议为所有资源使用此标头。
用法示例
X-Content-Type-Options: nosniff
建议用法
建议对从服务器传送的所有资源使用 X-Content-Type-Options: nosniff,并搭配正确的 Content-Type 标头。
随文档 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 标头。
防止您的网站被任何其他网站嵌入
拒绝被任何其他文档嵌入。
X-Frame-Options: DENY防止您的网站被任何跨域网站嵌入
仅允许由同源文档嵌入。
X-Frame-Options: SAMEORIGIN支持的浏览器
了解详情
跨域资源政策 (CORP)
攻击者可以嵌入来自其他来源(例如您的网站)的资源,通过利用基于 Web 的跨网站泄露来了解这些资源的相关信息。
Cross-Origin-Resource-Policy 通过指明可加载它的网站集来降低这种风险。该标头采用以下三个值之一:same-origin、same-site 和 cross-origin。建议所有资源都发送此标头,以指明是否允许其他网站加载它们。
用法示例
Cross-Origin-Resource-Policy: same-origin
建议用法
建议使用以下三个标头之一提供所有资源。
允许加载资源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() 或不含 rel="noopener" 的 target="_blank" 链接打开的跨域窗口隔离开来。因此,文档的任何跨域 opener 都不会引用该文档,也无法与其交互。
用法示例
Cross-Origin-Opener-Policy: same-origin-allow-popups
建议用法
将文档与跨域窗口隔离开来
设置 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标头中,经过身份验证的请求也会被拒绝。
预检请求
预检请求前面会有一个 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-TypeHTTP 标头。
示例响应标头
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: 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 迁移到 HTTPS 的网站在收到 HTTP 请求时,都应返回 Strict-Transport-Security 标头。
Strict-Transport-Security: max-age=31536000支持的浏览器