内容安全策略 (CSP)

内容安全策略 (CSP) 是一种额外的安全层,有助于检测和缓解某些类型的攻击,包括跨站脚本攻击 (XSS) 和数据注入攻击。这些攻击被用于从数据盗窃到网站篡改,再到恶意软件分发等各种目的。

CSP 旨在完全向后兼容(除了 CSP 版本 2 中有一些明确提到的向后兼容性不一致之处;更多详细信息在此第 1.1 节)。不支持 CSP 的浏览器仍然可以与实现 CSP 的服务器一起工作,反之亦然。不支持 CSP 的浏览器会忽略它,照常运行;它们只会应用标准同源策略的保护,而不会添加 CSP 会添加的进一步限制。

要启用 CSP,您需要配置您的 Web 服务器以返回Content-Security-Policy HTTP 标头。(有时您可能会看到X-Content-Security-Policy标头的提及,但那是旧版本,您不再需要指定它。)

或者,可以使用<meta>元素配置策略,例如

html
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; img-src https://*; child-src 'none';" />

注意:某些功能,例如发送 CSP 违规报告,仅在使用 HTTP 标头时可用。

威胁

缓解跨站脚本攻击

CSP 的主要目标是缓解和报告 XSS 攻击。XSS 攻击利用浏览器对从服务器接收到的内容的信任。恶意脚本由受害者的浏览器执行,因为浏览器信任内容的来源,即使它并非来自看起来的来源。

CSP 使服务器管理员能够通过指定浏览器应认为是可执行脚本的有效来源的域来减少或消除 XSS 可能发生的途径。然后,兼容 CSP 的浏览器只会执行从这些允许的域接收到的源文件中加载的脚本,忽略所有其他脚本(包括内联脚本和事件处理 HTML 属性)。

作为一种终极保护形式,希望永远不允许执行脚本的站点可以选择全局禁止脚本执行。

缓解数据包嗅探攻击

除了限制可以从中加载内容的域之外,服务器还可以指定允许使用哪些协议;例如(从安全的角度来看,理想情况下),服务器可以指定所有内容都必须使用 HTTPS 加载。完整的的数据传输安全策略不仅包括强制执行 HTTPS 进行数据传输,还包括标记所有带有secure属性的 Cookie,并提供从 HTTP 页面到其 HTTPS 对应页面的自动重定向。站点还可以使用Strict-Transport-Security HTTP 标头来确保浏览器仅通过加密通道连接到它们。

使用 CSP

配置内容安全策略涉及将Content-Security-Policy HTTP 标头添加到网页中,并赋予其值以控制用户代理允许为该页面加载哪些资源。例如,上传和显示图像的页面可以允许来自任何地方的图像,但将表单操作限制到特定端点。正确设计的内容安全策略有助于保护页面免受跨站脚本攻击。本文介绍了如何正确构造此类标头,并提供了示例。

指定您的策略

您可以使用Content-Security-Policy HTTP 标头指定您的策略,如下所示

http
Content-Security-Policy: policy

策略是一个包含策略指令的字符串,描述您的内容安全策略。

编写策略

策略使用一系列策略指令来描述,每个指令描述特定资源类型或策略区域的策略。您的策略应包含default-src策略指令,当其他资源类型没有自己的策略时,它作为后备(有关完整列表,请参阅default-src指令的描述)。策略需要包含default-srcscript-src指令以防止内联脚本运行,以及阻止使用eval()。策略需要包含default-srcstyle-src指令以限制从<style>元素或style属性应用内联样式。针对各种类型的项目有特定的指令,以便每种类型都可以有自己的策略,包括字体、框架、图像、音频和视频媒体、脚本和工作线程。

有关策略指令的完整列表,请参阅Content-Security-Policy 标头的参考页面。

示例:常见用例

本节提供了一些常见安全策略场景的示例。

示例 1

网站管理员希望所有内容都来自网站自己的来源(这排除了子域)。

http
Content-Security-Policy: default-src 'self'

示例 2

网站管理员希望允许来自受信任域及其所有子域的内容(不必与设置 CSP 的域相同)。

http
Content-Security-Policy: default-src 'self' example.com *.example.com

示例 3

网站管理员希望允许 Web 应用程序的用户在其自己的内容中包含来自任何来源的图像,但将音频或视频媒体限制为受信任的提供商,并将所有脚本仅限于托管受信任代码的特定服务器。

http
Content-Security-Policy: default-src 'self'; img-src *; media-src example.org example.net; script-src userscripts.example.com

在这里,默认情况下,内容仅允许来自文档的来源,以下情况除外

  • 图像可以从任何地方加载(请注意“*”通配符)。
  • 媒体仅允许来自 example.org 和 example.net(而非来自这些站点的子域)。
  • 可执行脚本仅允许来自 userscripts.example.com。

示例 4

在线银行网站的网站管理员希望确保其所有内容都使用 TLS 加载,以防止攻击者窃听请求。

http
Content-Security-Policy: default-src https://onlinebanking.example.com

服务器仅允许访问通过单个来源 onlinebanking.example.com 通过 HTTPS 特定加载的文档。

示例 5

Web 邮件站点的网站管理员希望允许电子邮件中的 HTML 以及从任何地方加载的图像,但 JavaScript 或其他潜在的危险内容只能来自与邮件服务器相同的来源。

http
Content-Security-Policy: default-src 'self' *.example.com; img-src *

请注意,此示例未指定script-src,因此default-src指令将用作 JavaScript 源的后备。

测试您的策略

为了简化部署,CSP 可以以报告模式部署。策略不会被执行,但任何违规行为都会报告到提供的 URI。此外,可以使用仅报告标头来测试策略的未来修订版,而无需实际部署它。

您可以使用Content-Security-Policy-Report-Only HTTP 标头指定您的策略,如下所示

http
Content-Security-Policy-Report-Only: policy

如果在同一个响应中同时存在Content-Security-Policy-Report-Only标头和Content-Security-Policy标头,则两个策略都会被遵守。Content-Security-Policy标头中指定的策略会被执行,而Content-Security-Policy-Report-Only策略会生成报告,但不会被执行。

违规报告

报告 CSP 违规的推荐方法是使用Reporting API,在Reporting-Endpoints中声明端点,并使用Content-Security-Policy标头的report-to指令将其中一个指定为 CSP 报告目标。

警告:您还可以使用 CSP report-uri指令指定 CSP 违规报告的目标 URL。这通过带有application/csp-reportContent-TypePOST操作发送略有不同的 JSON 报告格式。这种方法已弃用,但您应该同时声明两者,直到report-to在所有浏览器中都得到支持。有关此方法的更多信息,请参阅report-uri主题。

服务器可以使用Reporting-Endpoints HTTP 响应标头通知客户端发送报告的位置。此标头将一个或多个端点 URL 定义为逗号分隔列表。例如,要定义名为csp-endpoint的报告端点,该端点在https://example.com/csp-reports处接受报告,服务器的响应标头可能如下所示

http
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"

如果您希望有多个处理不同类型报告的端点,则会像这样指定它们

http
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports",
                     hpkp-endpoint="https://example.com/hpkp-reports"

然后,您可以使用Content-Security-Policy标头的report-to指令指定应将特定定义的端点用于报告。例如,要将 CSP 违规报告发送到https://example.com/csp-reports以用于default-src,您可能会发送如下所示的响应标头

http
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"
Content-Security-Policy: default-src 'self'; report-to csp-endpoint

发生 CSP 违规时,浏览器会将报告作为 JSON 对象通过 HTTP POST操作发送到指定的端点,并使用application/reports+jsonContent-Type。报告是包含值为“csp-violation”的type属性以及作为CSPViolationReportBody对象的序列化形式的bodyReport对象的序列化形式。

一个典型的对象可能如下所示

json

{
  "age": 53531,
  "body": {
    "blockedURL": "inline",
    "columnNumber": 39,
    "disposition": "enforce",
    "documentURL": "https://example.com/csp-report",
    "effectiveDirective": "script-src-elem",
    "lineNumber": 121,
    "originalPolicy": "default-src 'self'; report-to csp-endpoint-name",
    "referrer": "https://www.google.com/",
    "sample": "console.log(\"lo\")",
    "sourceFile": "https://example.com/csp-report",
    "statusCode": 200
  },
  "type": "csp-violation",
  "url": "https://example.com/csp-report",
  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}

您需要设置一个服务器来接收使用给定 JSON 格式和内容类型的报告。处理这些请求的服务器可以以最适合您需求的方式存储或处理传入的报告。

浏览器兼容性

BCD 表格仅在启用

兼容性说明

Safari 浏览器的一些版本存在特定不兼容性,即如果设置了内容安全策略标头,但未设置同源标头,则浏览器将阻止自托管内容和异地内容,并错误地报告这是由于内容安全策略不允许该内容导致的。

另请参阅