安全标头快速参考

详细了解可保障网站安全并快速查找最重要的详细信息的标题。

阿图尔·扬克
Artur Janc
毛德·纳尔帕斯
毛德·纳尔帕斯

本文列出了可用于保护网站的最重要的安全标头。通过学习本指南,您可以了解基于网络的安全功能,了解如何在您的网站上实现这些功能,并在您需要提醒时参考。

对于处理敏感用户数据的网站,建议采用以下安全标头:
内容安全政策 (CSP)
可信类型
建议为所有网站使用的安全标头:
X-Content-Type-Options
X-Frame-Options
跨域资源政策 (CORP)
跨域开放者政策 (COOP)
HTTP 严格传输安全协议 (HSTS)
具有高级功能的网站的安全标头:
跨域资源共享 (CORS)
跨域嵌入器政策 (COEP)
网络上的已知威胁
在深入了解安全标头之前,请了解 Web 上的已知威胁以及使用这些安全标头的原因。

在深入了解安全标头之前,请了解 Web 上的已知威胁以及使用这些安全标头的原因。

保护您的网站免受注入漏洞的影响

如果您的应用处理的不可信数据可能影响其行为,并且通常会导致执行受攻击者控制的脚本,则可能会出现注入漏洞。由注入 bug 导致的最常见漏洞是各种形式的跨站脚本攻击 (XSS),包括反射 XSS存储的 XSS基于 DOM 的 XSS 和其他变体。

XSS 漏洞通常会导致攻击者能够完全访问应用所处理的用户数据和同一来源中托管的所有其他信息。

传统的注入防御措施包括:一致地使用自动转义 HTML 模板系统、避免使用危险的 JavaScript API,以及通过在单独的网域中托管文件上传并清理用户控制的 HTML 来正确处理用户数据。

将您的网站与其他网站隔离开来

网络的开放性让网站能够以可能违反应用安全预期的方式相互交互。这包括意外发出经过身份验证的请求,或者将其他应用的数据嵌入攻击者的文档中,从而使攻击者能够修改或读取应用数据。

破坏网络隔离的常见漏洞包括点击劫持跨站请求伪造 (CSRF)、跨站脚本包含 (XSSI) 和各种跨站泄露

如果您对这些头文件感兴趣,不妨阅读 Post-Spectre Web 开发

安全地构建功能强大的网站

尽管存在同源政策Spectre 会将加载到同一浏览上下文组的任何数据都放置为可能读取的数据。浏览器会限制某些功能,这些功能可能会利用名为“跨域隔离”的特殊环境背后存在的漏洞。借助跨域隔离,您可以使用 SharedArrayBuffer 等强大的功能。

对流向您网站的流量进行加密

如果应用未对传输中的数据进行完全加密,就会出现加密问题,导致窃听攻击者了解用户与该应用的互动情况。

在以下情况下,可能会导致加密不足:不使用 HTTPS、混合内容、设置不含 Secure 属性(或 __Secure 前缀)的 Cookie,或放宽 CORS 验证逻辑

内容安全政策 (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';
如何使用 CSP

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 的其他注意事项

了解详情

可信类型

基于 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, '&lt;').replace(/>/g, '&gt;');
    }
  });
}

// Assignment of raw strings is blocked by Trusted Types.
el.innerHTML = &#39;some string&#39;; // This throws an exception.

// Assignment of Trusted Types is accepted safely.
const escaped = policy.createHTML(&#39;&lt;img src=x onerror=alert(1)&gt;&#39;);
el.innerHTML = escaped;  // &#39;&amp;lt;img src=x onerror=alert(1)&amp;gt;&#39;

如何使用可信类型

  1. 对危险的 DOM 接收器强制执行可信类型 CSP 和“可信类型”标头

    Content-Security-Policy: require-trusted-types-for 'script'
    

    'script'require-trusted-types-for 指令目前唯一可接受的值。

    当然,您可以将可信类型与其他 CSP 指令结合使用:

将上述基于 Nonce 的 CSP 与可信类型合并:

Content-Security-Policy:
  script-src &#39;nonce-{RANDOM1}&#39; &#39;strict-dynamic&#39; https: &#39;unsafe-inline&#39;;
  object-src &#39;none&#39;;
  base-uri &#39;none&#39;;
  require-trusted-types-for &#39;script&#39;;

<aside class="note"><b>注意</b>:您可以通过设置额外的 <code>trusted-types</code> 指令(例如 <code>trusted-types myPolicy</code>)来限制允许的可信类型政策名称。不过,这并非强制性要求。</aside>

  1. 定义政策

    政策

    // Feature detection
    if (window.trustedTypes && trustedTypes.createPolicy) {
      // Name and create a policy
      const policy = trustedTypes.createPolicy('escapePolicy', {
        createHTML: str => {
          return str.replace(/\/g, '>');
        }
      });
    }
    
  2. 应用政策

    将数据写入 DOM 时,使用该政策

    // Assignment of raw strings are blocked by Trusted Types.
    el.innerHTML = &#39;some string&#39;; // This throws an exception.</p>
    
    <p>// Assignment of Trusted Types is accepted safely.
    const escaped = policy.createHTML(&#39;<img src="x" onerror="alert(1)">&#39;);
    el.innerHTML = escaped;  // &#39;&lt;img src=x onerror=alert(1)&gt;&#39;
    

    使用 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
如何使用 X-Content-Type-Options

对于从您的服务器提供的所有资源以及正确的 Content-Type 标头,建议使用 X-Content-Type-Options: nosniff

X-Content-Type-Options: nosniff

随文档 HTML 发送的标头示例

X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8

支持的浏览器

浏览器支持

  • 64
  • 12
  • 50
  • 11

来源

了解详情

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: DENY

防止您的网站被任何跨源网站嵌入

仅允许同源文档嵌入。

X-Frame-Options: SAMEORIGIN

支持的浏览器

浏览器支持

  • 4
  • 12
  • 4
  • 4

来源

了解详情

跨域资源政策 (CORP)

攻击者可以嵌入来自其他来源(例如来自您的网站)的资源,通过利用基于网络的跨网站泄露功能来了解这些资源。

Cross-Origin-Resource-Policy 通过指明它可加载的网站集来降低此风险。标头采用以下三个值之一:same-originsame-sitecross-origin。建议所有资源发送此标头,以指明是否允许其他网站加载这些资源。

用法示例

Cross-Origin-Resource-Policy: same-origin
如何使用 CORP

建议为所有资源提供以下三个标头之一。

您可以在此演示中试用以下配置如何影响 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 响应的资源。

请注意,具有此标头的资源仍然可以直接加载,例如通过在新浏览器窗口中导航到相应网址。跨域资源政策只能防止该资源被其他网站嵌入。

跨源资源政策:Same-origin
Cross-Origin-Resource-Policy: same-origin

限制从 same-site 加载的资源

建议将 same-site 应用于与上述内容类似但打算由您网站的其他子网域加载的资源。

跨源资源政策:Same-site
Cross-Origin-Resource-Policy: same-site

支持的浏览器

浏览器支持

  • 73
  • 79
  • 74
  • 12

来源

了解详情

跨域打开者政策 (COOP)

攻击者的网站可利用基于 Web 的跨网站泄露,在弹出式窗口中打开其他网站,了解其相关信息。在某些情况下,这还可能会允许基于 Spectre 的边信道攻击被利用。

借助 Cross-Origin-Opener-Policy 标头,文档可将自身与通过 window.open() 打开的跨源窗口或带有 target="_blank"(不带 rel="noopener")的链接隔离开来。因此,文档的任何跨源 opener 都没有引用,且无法与之交互。

用法示例

Cross-Origin-Opener-Policy: same-origin-allow-popups
如何使用 COOP

您可以在此演示中尝试以下配置如何影响与跨源弹出式窗口的通信。 更改文档和弹出式窗口的 Cross-Origin-Opener-Policy 下拉菜单,依次点击 Open a 弹出式窗口按钮和 Send a postMessage,查看消息是否实际传送。

将文档与跨源窗口隔离开来

设置 same-origin 可将文档与跨源文档窗口隔离开来。

Cross-Origin-Opener-Policy:Same-origin
Cross-Origin-Opener-Policy: same-origin

将文档与跨源窗口隔离开来,但允许显示弹出式窗口

设置 same-origin-allow-popups 允许文档保留对其弹出式窗口的引用,除非文档使用 same-originsame-origin-allow-popups 设置 COOP。这意味着,same-origin-allow-popups 仍然可以保护该文档在以弹出式窗口形式打开时不会被引用,但允许它与其自己的弹出式窗口进行通信。

Cross-Origin-Opener-Policy:same-origin-allow-popups
Cross-Origin-Opener-Policy: same-origin-allow-popups

允许跨源窗口引用文档

unsafe-none 为默认值,但您可以明确指明此文档可由跨源窗口打开并保持相互访问。

Cross-Origin-Opener-Policy:不安全-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"

支持的浏览器

浏览器支持

  • 83
  • 83
  • 79
  • 15.2

来源

了解详情

跨源资源共享 (CORS)

与本文中的其他各项不同,跨域资源共享 (CORS) 不是标头,而是请求和允许访问跨源资源的浏览器机制。

默认情况下,浏览器会强制执行同源政策,以防止网页访问跨源资源。例如,加载跨源图片(即使它以可视化方式显示在网页上)时,页面上的 JavaScript 将无权访问图片的数据。资源提供商可以选择启用 CORS,从而放宽限制,并允许其他网站读取资源。

用法示例

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
如何使用 CORS

在了解如何配置 CORS 之前,了解请求类型之间的差异会很有帮助。根据请求详细信息,请求可分为简单请求或预检请求。

简单请求的条件:

  • 方法是 GETHEADPOST
  • 自定义头文件仅包含 AcceptAccept-LanguageContent-LanguageContent-Type
  • Content-Typeapplication/x-www-form-urlencodedmultipart/form-datatext/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-PINGOTHERContent-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 表示可以使用 POSTGETOPTIONS 方法发出后续请求。
  • Access-Control-Allow-Headers: X-PINGOTHER, Content-Type 表示后续请求可以包含 X-PINGOTHERContent-Type 标头。
  • Access-Control-Max-Age: 86400 表示预检请求的结果可以缓存 86400 秒。

支持的浏览器

浏览器支持

  • 4
  • 12
  • 3.5
  • 4

来源

了解详情

跨域嵌入器政策 (COEP)

为了降低基于 Spectre 的攻击窃取跨源资源的能力,SharedArrayBufferperformance.measureUserAgentSpecificMemory() 等功能默认处于停用状态。

Cross-Origin-Embedder-Policy: require-corp 可防止文档和工作器加载跨源资源(例如图片、脚本、样式表、iframe 等),除非这些资源明确选择通过 CORSCORP 标头加载。COEP 可以与 Cross-Origin-Opener-Policy 结合使用,为文档选择启用跨域隔离

如果要为文档启用跨域隔离,请使用 Cross-Origin-Embedder-Policy: require-corp

用法示例

Cross-Origin-Embedder-Policy: require-corp
如何使用 COEP

用法示例

COEP 只接受一个 require-corp 值。通过发送此标头,您可以指示浏览器阻止加载未通过 CORSCORP 选择启用的资源。

COEP 的运作方式

您可以在此演示中尝试以下配置如何影响加载资源。更改 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"

支持的浏览器

浏览器支持

  • 83
  • 83
  • 79
  • 15.2

来源

了解详情

HTTP 严格传输安全协议 (HSTS)

通过普通 HTTP 连接进行的通信不加密,因此网络级窃听者可以访问传输的数据。

Strict-Transport-Security 标头会告知浏览器,切勿使用 HTTP 来加载网站,而应改用 HTTPS。设置完成后,在标头中指定的时长内,浏览器将使用 HTTPS(而非 HTTP)访问网域,而不会进行重定向。

用法示例

Strict-Transport-Security: max-age=31536000
如何使用 HSTS

在收到 HTTP 请求时,从 HTTP 转换为 HTTPS 的所有网站都应使用 Strict-Transport-Security 标头进行响应。

Strict-Transport-Security: max-age=31536000

支持的浏览器

浏览器支持

  • 4
  • 12
  • 4
  • 7

来源

了解详情

补充阅读材料