内容安全政策 (CSP) 有助于确保网页中加载的所有内容均受到网站所有者的信任。CSP 可以阻止攻击者注入的不安全脚本,从而缓解跨站脚本攻击 (XSS) 攻击。不过,如果 CSP 不够严格,可以轻松绕过 CSP。如需了解详情,请参阅使用严格的内容安全政策 (CSP) 来缓解跨站脚本攻击 (XSS)。Lighthouse 会收集在主文档上强制执行的 CSP,并通过 CSP Evaluator 报告可绕过的问题。
<ph type="x-smartling-placeholder">不可绕过的 CSP 的必需做法
请遵��以下做法,以确保无法绕过您的 CSP。如果可以绕过 CSP,Lighthouse 将发出高严重级别的警告。
CSP 目标 XSS
如需以 XSS 为目标,CSP 应包含 script-src
、object-src
和 base-uri
指令。CSP 也应没有语法错误。
script-src
和 object-src
分别用于保护网页免受不安全脚本和不安全插件的侵害。此外,您还可以使用 default-src
配置宽泛的政策,以取代许多指令,包括 script-src
和 object-src
。
base-uri
可防止注入未经授权的 <base>
标记,此类标记可用于将所有相对网址(例如脚本)重定向到攻击者控制的网域。
CSP 使用 Nonce 或哈希值来避免绕过许可名单
CSP 在为 script-src
配置许可名单时,依赖于这样的假设:来自受信任网域的所有响应都是安全的,并且可以作为脚本执行。然而,这种假设并不适用于现代应用。一些常见的良性模式(例如公开 JSONP 接口和托管 AngularJS 库的副本)会让攻击者逃离 CSP 的限制。
在实践中,尽管应用作者可能并不明显,但大多数 script-src
许可名单可能会被攻击者利用 XSS bug 规避,并且几乎无法防范脚本注入。相比之下,基于 Nonce 和基于哈希的方法不会遇到这些问题,并且更容易采用和维护更安全的策略。
例如,以下代码使用托管在可信网域上的 JSONP 端点注入由攻击者控制的脚本:
CSP:
script-src https://trusted.example.com
HTML:
<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>
为避免被绕过,CSP 应分别允许脚本使用 Nonce 或哈希值,并使用“strict-dynamic”而非许可名单
关于安全 CSP 的其他建议
为提高安全性和兼容性,请遵循以下做法。如果 CSP 未遵循任何建议,则 Lighthouse 会发出中等严重级别的警告。
配置 CSP 报告
配置报告目标位置有助于监控任何损坏情况。您可以使用 report-uri
或 report-to
指令设置报告目标位置。目前,并非所有现代浏览器都支持 report-to
,因此建议您同时使用两者或仅使用 report-uri
。
如有任何内容违反 CSP,浏览器会向配置的目标位置发送报告。请确保您已在此目标中配置了一个能够处理这些报告的应用。
在 HTTP 标头中定义 CSP
CSP 可在元标记中定义,如下所示:
<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
不过,如果可以,您应在 HTTP 响应标头中定义 CSP。在元标记之前的插入内容将绕过 CSP。此外,元标记 CSP 不支持 frame-ancestors
、sandbox
和报告。
确保 CSP 向后兼容
并非所有浏览器都支持 CSP nonces/hashes,因此建议添加 unsafe-inline
作为不合规浏览器的回退方案。如果浏览器支持 Nonce/hash,unsafe-inline
将会被忽略。
同样,并非所有浏览器都支持 strict-dynamic
。建议将许可名单设为后备所有不符合政策规定的浏览器。在支持 strict-dynamic
的浏览器中,系统会忽略许可名单。
如何制定严格的 CSP
以下是将严格 CSP 与基于 Nonce 的政策结合使用的示例。
CSP:
script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;
HTML:
<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>
每次网页加载时,random123
都是服务器端生成的任意 base64 字符串。由于 Nonce 和 strict-dynamic
,在现代浏览器中会忽略 unsafe-inline
和 https:
。如需详细了解如何采用严格的 CSP,请参阅严格 CSP 指南。
您可以使用 Lighthouse 和 CSP Evaluator 检查 CSP 是否存在可能的绕过情况。如果您希望在不破坏现有网页的风险的情况下测试新的 CSP,请使用 Content-Security-Policy-Report-Only
作为标题名���,在“仅限报告”模式下定义 CSP。这会将 CSP 违规行为发送到您使用 report-to
和 report-uri
配置的所有报告目标,但实际上并不会强制执行 CSP。