精进的内容安全策略

内容安全策略标准允许您定义页面允许加载的内联脚本、内联样式表和子资源的列表。您可以在每个页面上定义内容安全策略,以限制在页面存在内容注入漏洞时攻击者可能拥有的能力。如果您的页面显示用户生成的内容(例如,渲染由其所有者提供或影响的标记的用户个人资料页面),则可以使用内容安全策略来限制此类内容的能力。将内容安全策略视为应对编码错误的保险策略。

最新 WebKit 构建版本和 Safari 技术预览版现在支持 内容安全策略 Level 2 标准 的所有特性,包括脚本和样式元素的哈希。

<script> 和 <style> 哈希

您现在可以通过在您的 CSP 中包含内联脚本或内联样式表内容的加密哈希来允许其加载。哈希使得在必须包含内联脚本和内联样式表的现有页面上采用内容安全策略变得容易。将页面上每个内联 <script><style> 内容的 SHA-256、SHA-384 或 SHA-512 哈希添加到您的策略中,以允许这些元素加载,并防止加载未在用户生成的内容中正确转义或更糟的是被攻击者注入的任意内联脚本和内联样式表。使用哈希还可以避免向您的策略添加有风险的 'unsafe-inline' 关键字。

让我们看一个例子。如果您正在使用最新的 WebKit 构建版本或 Safari 技术预览版,然后您点击这里,那么您将看到蓝色方块内的 WebKit 指南针的白色轮廓。否则,您将看到一个蓝色方块。这是页面的 CSP meta 标签

<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'sha256-G0CufoWPLTm5OhVU1OioVsF0ge/f2hWhXLJHu3QH0bQ='; img-src 'self'; default-src 'none'">

加载指南针图像的内联样式表具有哈希源表达式 'sha256-G0CufoWPLTm5OhVU1OioVsF0ge/f2hWhXLJHu3QH0bQ='。它被允许加载,因为它的哈希出现在 CSP meta 标签中。

我们增强了 Web检查器,以在节点详细信息窗格中显示选定的脚本或样式元素的 CSP SHA-256 哈希表达式。

The CSP hash of the inline stylesheet in the example page is sha256-G0CufoWPLTm5OhVU1OioVsF0ge/f2hWhXLJHu3QH0bQ=.

这使您可以简单地在“元素”标签页中选择 <script><style>,并将“CSP 哈希”从节点详细信息侧边栏复制粘贴到您的策略中。这就是我如何获得 'sha256-G0CufoWPLTm5OhVU1OioVsF0ge/f2hWhXLJHu3QH0bQ=' 以用于上面的 CSP meta 标签。

支持 CSP 但不支持 CSP 哈希的浏览器将拒绝加载示例中的内联样式表。我们可以通过向我们的 meta 标签添加 'unsafe-inline',如下所示,使示例与此类浏览器向后兼容。添加的关键字将允许这些浏览器加载页面上所有样式元素的内容。支持 CSP 哈希的浏览器将忽略 'unsafe-inline' 关键字并执行哈希比较。

<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'sha256-G0CufoWPLTm5OhVU1OioVsF0ge/f2hWhXLJHu3QH0bQ=' 'unsafe-inline'; img-src 'self'; default-src 'none'">

WebKit 支持所有 CSP Level 2 哈希算法:SHA-256、SHA-384 和 SHA-512。即使您的策略可以包含混合了不同哈希算法的哈希,使用不止一种哈希算法可能导致浏览器执行不必要的哈希计算。如果您确实使用了哈希,则确保将它们添加到您的策略中最具体的指令中:script-src 用于脚本元素,style-src 用于样式元素。避免将哈希添加到 default-src 指令,因为它保证浏览器必须计算页面中每个脚本和样式元素的哈希并执行哈希比较。

更严格的通配符 *

历史上,CSP 策略是使用源表达式列表定义的,用于匹配页面允许加载的子资源的 URL。源表达式 * 是一个通配符表达式,匹配任何非 data: 或 blob: 的 URL。WebKit 进一步限制了 * 可以匹配的 URL scheme,以防止您在无意中允许从这些特殊 scheme 加载,而此类加载可能被用户生成的内容或攻击者利用来运行任意代码。此更改是向后不兼容的更改,代表了在网络兼容性与缓解使用 * 的站点中的内容注入漏洞之间的谨慎平衡。此更改的优点是它使得 * 具有更安全的默认行为。缺点是您需要明确地将特殊 scheme 和自定义协议添加到您的策略中,以便允许从它们加载。这是 * 出现在各种指令的源列表时所匹配的 scheme 的综合细分

指令 * 匹配
img-src “页面协议”, http:, https:, data
media-src “页面协议”, http:, https:, data:, blob
其他 “页面协议”, http:, https

我们认为允许 * 匹配用于图像的 data: 以及用于媒体的 data:blob: 是可以接受的,因为嵌入在这些 scheme 的 URL 中的 JavaScript 代码通过 <img><video><audio> 加载时不会执行。

如前所述,如果您开发了一个嵌入 web view 并通过自定义协议加载资源的应用程序,您需要在策略中明确将任何自定义协议列入白名单。例如,如果您想将图像加载限制为常用 scheme 和您自己的自定义协议 app:,您将使用

<meta http-equiv="Content-Security-Policy" content="img-src * app:">

欢迎反馈

像往常一样,在 bugs.webkit.org 报告您在内容安全策略中发现的任何 bug。对于评论或问题,请随时在 Twitter 上通过 @WebKit 或联系我们的 Web 技术布道师 Jonathan Davis,在 @jonathandavis。请尽情尝试!