详细了解有助于确保网站安全的标头,并快速查找最重要的详细信息。
本文列出了可用于保护网站的最重要的安全标头。您可以使用它来了解基于 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、存在混合内容、设置 Cookie 时未添加 Secure 属性(或 __Secure 前缀)或存在宽松的 CORS 验证逻辑。
- 使用 HTTP 严格传输安全协议 (HSTS) 通过 HTTPS 持续传送您的内容。
内容安全政策 (CSP)
跨站脚本攻击 (XSS) 是一种攻击,其中网站上的漏洞允许注入和执行恶意脚本。
Content-Security-Policy 通过限制网页可执行的脚本来提供额外的层,以缓解 XSS 攻击。
建议您使用以下方法之一启用严格的 CSP:
- 如果您在服务器上呈现 HTML 网页,请使用基于 Nonce 的严格 CSP。
- 如果您的 HTML 必须静态提供或缓存,例如,如果它是单页应用,请使用基于哈希的严格 CSP。
用法示例:基于随机数的 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 的好工具,同时也是基于随机数的严格 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 接收器强制执行 Trusted Types CSP 和 Trusted Types 标头:
Content-Security-Policy: require-trusted-types-for 'script'目前,
'script'是require-trusted-types-for指令唯一可接受的值。当然,您可以将可信类型与其他 CSP 指令结合使用:
将上述基于随机数的 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>)来限制允许的可信类型政策名称。不过,这不是必需的。</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 标头。