确保 CSP 能够有效防范 XSS 攻击
内容安全政策 (CSP) 有助于确保网站所有者信任网页中加载的所有内容。CSP 可以阻止攻击者注入的不安全脚本,从而缓解跨站脚本攻击 (XSS) 攻击。不过,如果 CSP 不够严格,则可以轻松绕过 CSP。如需了解详情,请参阅通过严格的内容安全政策 (CSP) 缓解跨站脚本攻击 (XSS)。Lighthouse 会收集在主文档中强制执行的 CSP,并报告 CSP Evaluator 中无法绕过的问题。
Lighthouse 报告警告:在强制执行模式下找不到 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 bug 的攻击者规避,并且几乎无法防范脚本注入。相比之下,基于 Nonce 和基于哈希的方法不会遇到这些问题,并且更容易采用和维护更安全的政策。
例如,以下代码使用托管在受信任网域中的 JSONP 端点来注入由攻击者控制的脚本:
内容安全政策:
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
作为不合规浏览器的后备方案。如果浏览器支持 nonces/hashes,则 unsafe-inline
会被忽略。
同样,并非所有浏览器都支持 strict-dynamic
。建议将许可名单设为所有不合规浏览器的后备选项。在支持 strict-dynamic
的浏览器中,许可名单会被忽略。
如何开发严格的 CSP
以下示例展示了如何将严格 CSP 与基于 Nonce 的政策搭配使用。
内容安全政策:
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。
Statement: If the content on this site infringes upon the legitimate rights and interests of the original author, please contact this site to delete it.