内容安全政策 (CSP) 有助于确保在网页中加载的所有内容都受网站所有者信任。CSP 可以缓解跨站脚本攻击 (XSS),因为它们可以阻止攻击者注入的不可信脚本。但是,如果 CSP 不够严格,则很容易被绕过。如需了解详情,请参阅通过严格的内容安全政策 (CSP) 防范跨站脚本攻击 (XSS)。Lighthouse 会收集对主文档强制执行的 CSP,并报告 CSP 评估器中的问题(如果可以绕过)。
不可绕过的 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 或哈希来避免绕过许可名单
为 script-src
配置许可名单的 CSP 假定来自受信任网域的所有响应都是安全的,并且可以作为脚本执行。不过,对于现代应用,这种假设并不适用;一些常见的良性模式(例如公开 JSONP 接口和托管 AngularJS 库的副本)会让攻击者逃脱 CSP 的限制。
在实践中,虽然应用作者可能并不清楚,但大多数 script-src
许可名单都可以被利用 XSS 漏洞的攻击者规避,并且对脚本注入几乎没有保护作用。相比之下,基于 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 nonce/hash,因此建议您添加 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 评估程序检查 CSP 是否存在潜在的绕过方法。如果您想测试新的 CSP,但不希望破坏现有网页,请使用 Content-Security-Policy-Report-Only
作为标头名称,以报告模式定义 CSP。这会将 CSP 违规情况发送到您使用 report-to
和 report-uri
配置的任何报告目的地,但实际上不会强制执行 CSP。