内容安全策略 (CSP)
内容安全策略 (CSP) 是一种额外的安全层,有助于检测和缓解某些类型的攻击,包括跨站脚本攻击 (XSS) 和数据注入攻击。这些攻击被用于从数据盗窃到网站篡改,再到恶意软件分发等各种目的。
CSP 旨在完全向后兼容(除了 CSP 版本 2 中有一些明确提到的向后兼容性不一致之处;更多详细信息在此第 1.1 节)。不支持 CSP 的浏览器仍然可以与实现 CSP 的服务器一起工作,反之亦然。不支持 CSP 的浏览器会忽略它,照常运行;它们只会应用标准同源策略的保护,而不会添加 CSP 会添加的进一步限制。
要启用 CSP,您需要配置您的 Web 服务器以返回Content-Security-Policy
HTTP 标头。(有时您可能会看到X-Content-Security-Policy
标头的提及,但那是旧版本,您不再需要指定它。)
或者,可以使用<meta>
元素配置策略,例如
<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 标头指定您的策略,如下所示
Content-Security-Policy: policy
策略是一个包含策略指令的字符串,描述您的内容安全策略。
编写策略
策略使用一系列策略指令来描述,每个指令描述特定资源类型或策略区域的策略。您的策略应包含default-src
策略指令,当其他资源类型没有自己的策略时,它作为后备(有关完整列表,请参阅default-src
指令的描述)。策略需要包含default-src
或script-src
指令以防止内联脚本运行,以及阻止使用eval()
。策略需要包含default-src
或style-src
指令以限制从<style>
元素或style
属性应用内联样式。针对各种类型的项目有特定的指令,以便每种类型都可以有自己的策略,包括字体、框架、图像、音频和视频媒体、脚本和工作线程。
有关策略指令的完整列表,请参阅Content-Security-Policy 标头的参考页面。
示例:常见用例
本节提供了一些常见安全策略场景的示例。
示例 1
网站管理员希望所有内容都来自网站自己的来源(这排除了子域)。
Content-Security-Policy: default-src 'self'
示例 2
网站管理员希望允许来自受信任域及其所有子域的内容(不必与设置 CSP 的域相同)。
Content-Security-Policy: default-src 'self' example.com *.example.com
示例 3
网站管理员希望允许 Web 应用程序的用户在其自己的内容中包含来自任何来源的图像,但将音频或视频媒体限制为受信任的提供商,并将所有脚本仅限于托管受信任代码的特定服务器。
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 加载,以防止攻击者窃听请求。
Content-Security-Policy: default-src https://onlinebanking.example.com
服务器仅允许访问通过单个来源 onlinebanking.example.com 通过 HTTPS 特定加载的文档。
示例 5
Web 邮件站点的网站管理员希望允许电子邮件中的 HTML 以及从任何地方加载的图像,但 JavaScript 或其他潜在的危险内容只能来自与邮件服务器相同的来源。
Content-Security-Policy: default-src 'self' *.example.com; img-src *
请注意,此示例未指定script-src
,因此default-src
指令将用作 JavaScript 源的后备。
测试您的策略
为了简化部署,CSP 可以以报告模式部署。策略不会被执行,但任何违规行为都会报告到提供的 URI。此外,可以使用仅报告标头来测试策略的未来修订版,而无需实际部署它。
您可以使用Content-Security-Policy-Report-Only
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-report
的Content-Type
的POST
操作发送略有不同的 JSON 报告格式。这种方法已弃用,但您应该同时声明两者,直到report-to
在所有浏览器中都得到支持。有关此方法的更多信息,请参阅report-uri
主题。
服务器可以使用Reporting-Endpoints
HTTP 响应标头通知客户端发送报告的位置。此标头将一个或多个端点 URL 定义为逗号分隔列表。例如,要定义名为csp-endpoint
的报告端点,该端点在https://example.com/csp-reports
处接受报告,服务器的响应标头可能如下所示
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"
如果您希望有多个处理不同类型报告的端点,则会像这样指定它们
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
,您可能会发送如下所示的响应标头
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+json
的Content-Type
。报告是包含值为“csp-violation”的type
属性以及作为CSPViolationReportBody
对象的序列化形式的body
的Report
对象的序列化形式。
一个典型的对象可能如下所示
{
"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 浏览器的一些版本存在特定不兼容性,即如果设置了内容安全策略标头,但未设置同源标头,则浏览器将阻止自托管内容和异地内容,并错误地报告这是由于内容安全策略不允许该内容导致的。
另请参阅
Content-Security-Policy
HTTP 标头Content-Security-Policy-Report-Only
HTTP 标头- WebExtensions 中的内容安全
- Web Workers 中的 CSP
- 隐私、权限和信息安全
- CSP 评估器 - 评估您的内容安全策略