详细了解可确保网站安全的标头,并快速查找最重要的详细信息。
本文列出了可用于保护您网站的最重要的安全标头。您可以通过该指南了解基于 Web 的安全功能,了解如何在网站上实现这些功能,并在需要提醒时作为参考。
- 建议处理敏感用户数据的网站添加以下安全标头:
- 内容安全政策 (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 类型,这可能会导致脚本执行。
将您的网站与其他网站隔离
由于 Web 的开放性,网站之间可以以违反应用安全预期的方式进行互动。这包括意外发出经过身份验证的请求,或在攻击者的文档中嵌入来自其他应用的数据,从而允许攻击者修改或读取应用数据。
破坏 Web 隔离的常见漏洞包括点击劫持、跨站请求伪造 (CSRF)、跨站脚本包含 (XSSI) 以及各种跨站数据泄露。
- 使用 X-Frame-Options 可防止恶意网站嵌入您的文档。
- 使用跨源资源政策 (CORP) 可防止跨源网站包含您网站的资源。
- 使用跨源开放者政策 (COOP) 可保护您网站的窗口免受恶意网站的互动影响。
- 使用跨源资源共享 (CORS) 控制对跨源文档中网站资源的访问权限。
如果您对这些标头感兴趣,不妨阅读“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 评估程序是一款评估 CSP 的绝佳工具,同时也是基于 Nonce 的严格 CSP 的绝佳示例。使用开发者工具查看其使用方式。
支持的浏览器
关于 CSP 的其他注意事项
frame-ancestors
指令可保护您的网站免受点击欺骗攻击,如果您允许不可信的网站嵌入您的网站,就会面临这种风险。如果您更喜欢更简单的解决方案,可以使用X-Frame-Options
阻止加载,但frame-ancestors
提供了高级配置,可仅允许特定来源作为嵌入程序。- 您可能已使用 CSP 确保网站的所有资源均通过 HTTPS 加载。这已不再那么重要:如今,大多数浏览器都会屏蔽混合内容。
- 您还可以在仅报告模式下设置 CSP。
- 如果您无法在服务器端将 CSP 设置为标头,也可以将其设置为元标记。请注意,您无法对元标记使用仅生成报告模式(不过这可能会发生变化)。
了解详情
可信类型
基于 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 与字符串搭配使用都会导致错误。
支持的浏览器
了解详情
- 使用可信类型防范基于 DOM 的跨站脚本漏洞
- CSP:require-trusted-types-for - HTTP |
MDN
- CSP:trusted-types - HTTP |
MDN
- “受信任类型”演示 - 打开 DevTools 检查器,了解正在发生的情况
X-Content-Type-Options
如果恶意 HTML 文档是从您的网域中提交的(例如,上传到照片服务的图片包含有效的 HTML 标记),某些浏览器会将其视为有效文档,并允许其在应用上下文中执行脚本,从而导致跨网站脚本漏洞。
X-Content-Type-Options: nosniff
通过指示浏览器为给定响应在 Content-Type
标头中设置的 MIME 类型正确无误来防止这种情况。建议为您的所有资源添加此标头。
用法示例
X-Content-Type-Options: nosniff
如何使用 X-Content-Type-Options
建议的用法
建议为从服务器提供的所有资源添加 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
标头。
您可以试用此演示,了解以下配置对加载 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
如何使用 CORP
建议的用法
建议为所有资源提供以下三个标头之一。
您可以通过此演示试用以下配置对 Cross-Origin-Embedder-Policy: require-corp
环境下加载资源的影响。更改 Cross-Origin-Resource-Policy 下拉菜单,然后点击 Reload the iframe 或 Reload the image 按钮以查看效果。
允许加载资源 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)
攻击者的网站可以利用基于网页的跨网站数据泄露,在弹出式窗口中打开另一个网站,以了解该网站的相关信息。在某些情况下,这可能还会允许利用基于 Spectre 的旁道攻击。
Cross-Origin-Opener-Policy
标头提供了一种方法,可让文档与通过 window.open()
打开的跨源窗口或不带 rel="noopener"
的 target="_blank"
链接隔离。因此,文档的任何跨源打开器都不会引用它,也无法与它互动。
用法示例
Cross-Origin-Opener-Policy: same-origin-allow-popups
如何使用 COOP
建议的用法
您可以试用此演示,了解以下配置对与跨源弹出式窗口的通信有何影响。
更改文档和弹出式窗口的 Cross-Origin-Opener-Policy 下拉菜单,点击 Open a popup 按钮,然后点击 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
在了解如何配置 CORS 之前,了解请求类型之间的区别会很有帮助。根据请求详情,请求会被归类为简单请求或预检请求。
简单请求的条件:
- 方法为
GET
、HEAD
或 POST
。
- 自定义标头仅包括
Accept
、Accept-Language
、Content-Language
和 Content-Type
。
Content-Type
为 application/x-www-form-urlencoded
、multipart/form-data
或 text/plain
。
所有其他请求都被归类为预先飞行请求。如需了解详情,请参阅 Cross-Origin Resource Sharing (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
环境下加载资源。点击 Cross-Origin Resource Sharing 复选框,然后点击 Reload the image 按钮以查看效果。
预检请求
预检请求之前会有一个 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
用法示例
COEP 采用单个值 require-corp
。通过发送此标头,您可以指示浏览器阻止加载未通过 CORS 或 CORP 选择启用的资源。
您可以试试以下配置对此演示中加载资源的影响。更改 Cross-Origin-Embedder-Policy 下拉菜单、Cross-Origin-Resource-Policy 下拉菜单、仅报告复选框等,看看它们对加载资源有何影响。此外,请打开报告端点演示,看看系统是否报告了被屏蔽的资源。
启用跨源隔离
通过将 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
如何使用 HSTS
建议的用法
从 HTTP 迁移到 HTTPS 的所有网站在收到使用 HTTP 的请求时都应使用 Strict-Transport-Security
标头进行响应。
Strict-Transport-Security: max-age=31536000
支持的浏览器
了解详情
深入阅读