内容安全策略:CSP 是否应该包含外部脚本的哈希值?

Content Security Policy: Should a CSP contain hashes for external scripts?

我不确定的地方

我想知道 Content-Security-Policy header should/can 是否包含 external JavaScript files 的哈希值(又名,具有 src 属性的标签 <script src="foo.js"></script> ).

我试过的

在基于 Chromium 的浏览器和 Mozilla Firefox 中,我的外部脚本被阻止,即使在 Content-Security-Policy header:

中包含所有这些脚本的哈希值也是如此
script-src 'sha256-Dxn+cR58x5haydQ1S/lvgMBLRahDCNxsakeubYGDJD0=' 'sha256-WiXxwK6878G5m29xzbpoI/6mHv7Otw1epCuigPupglA=' 'sha256-B5Xt87JgO41oTYQ2MabCc4UUuiVbcT/ingSs4HJHt1U=';

我也试过了

script-src 'strict-dynamic' 'sha256-Dxn+cR58x5haydQ1S/lvgMBLRahDCNxsakeubYGDJD0=' 'sha256-WiXxwK6878G5m29xzbpoI/6mHv7Otw1epCuigPupglA=' 'sha256-B5Xt87JgO41oTYQ2MabCc4UUuiVbcT/ingSs4HJHt1U=';

我的 HTML 包含外部脚本:

...

        <!-- These are Webpack generated scripts built with the Angular CLI -->
        <script src="runtime.78e54b12002286474edb.js"></script>
        <script src="polyfills.73e66b75888e8a86f685.js"></script>
        <script src="main.4deb3029247017da53f3.js"></script>
    </body>
</html>

我期望发生的事情

我希望浏览器对外部 JavaScript 文件的内容进行哈希处理,并将这些哈希值与 Content-Security-Policy header 的 script-src 属性中的哈希值进行比较(因此根据我的服务器在 CSP header 中列入白名单的内容验证任何交付的 JavaScript 文件的完整性)。

关于散列外部 JS 的 CSP 规范

Mozilla 在其 script-src 文档中声明。 注意最后一句

发件人:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src

'-'

脚本或样式的 sha256、sha384 或 sha512 哈希。此源的使用由破折号分隔的两部分组成:用于创建哈希的加密算法和脚本或样式的 base64 编码哈希。生成散列时,不要包含 或 标签,并注意大小写和空格很重要,包括前导或尾随空格。有关示例,请参见不安全的内联脚本。在 CSP 2.0 中,这仅适用于内联脚本。 CSP 3.0 允许在 script-src 的情况下用于外部脚本。

您提到的 MDN 文档只是流行信息,因此不包含详细信息。

根据 CSP3 spec,只有当 <script> 元素包含与策略中的哈希匹配的 完整性元数据 时,才允许执行这些元素。

integrity= 属性添加到脚本标签中,如下所示:

<!-- These are Webpack generated scripts built with the Angular CLI -->
<script src="runtime.78e54b12002286474edb.js" integrity="sha256-...."></script>
<script src="polyfills.73e66b75888e8a86f685.js" integrity="sha256-...."></script>
<script src="main.4deb3029247017da53f3.js" integrity="sha256-...."></script>

'hash-value'将开始工作。但是,不幸的是,在 Chrome only。 Safari 和 Firefox 还没有实现这个。