首页 > 解决方案 > 具有“严格动态”的外部脚本哈希需要脚本标签上的“完整性”属性?

问题描述

我正在研究网站的Content Security Policy,特别是strict-dynamic关键字。

我的测试站点有两个文件:

索引.html:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,user-scalable=yes" />
    <meta charset="UTF-8" />
    <title>csp-test</title>
  </head>
  <body>
    <h1>csp-test</h1>
    <script src="./index.js"></script>
  </body>
</html>

index.js:

console.log('foo');

我正在研究使用基于哈希的方法来允许脚本。

这是我在节点脚本中生成哈希的方式:

const input = fs.readFileSync("/path/to/index.js");
crypto.createHash("sha256").update(input, 'utf8').digest('base64')

这是结果index.js1kOLrDKT3TBiHLcnxiGsc7HF/lyVJKLhoZDSn0UwCfo=

使用此哈希,我将 CSP 配置更新为:

default-src 'self'; script-src 'self' 'strict-dynamic' 'sha256-1kOLrDKT3TBiHLcnxiGsc7HF/lyVJKLhoZDSn0UwCfo=' 'unsafe-inline'; object-src 'none'; base-uri 'self'

当我将此值作为具有此名称的响应标头(使用 ModHeader Chrome 扩展名)时,Content-Security-Policy-Report-Only我仍然在控制台中收到错误消息:

[Report Only] Refused to load the script 'http://localhost:5000/index.js' because it violates the following Content Security Policy directive: "script-src 'self' 'strict-dynamic' 'sha256-1kOLrDKT3TBiHLcnxiGsc7HF/lyVJKLhoZDSn0UwCfo=' 'unsafe-inline'". 'strict-dynamic' is present, so host-based allowlisting is disabled. Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

我可以通过integrity在我的脚本标签上设置属性来消除这个错误:

<script integrity="sha256-1kOLrDKT3TBiHLcnxiGsc7HF/lyVJKLhoZDSn0UwCfo=" src="./index.js"></script>

我的问题是:为什么我需要添加integrity属性? 我没有在文档中看到它,需要添加这个属性会使我们的构建过程更加复杂。是否需要指定此属性的替代方法?

标签: javascriptcontent-security-policy

解决方案


为什么我需要添加完整性属性?我没有在文档中看到它,需要添加这个属性会使我们的构建过程更加复杂。

MDN 仅包含解释 CSP 工作原理的常见内容。所有细节都在CSP 规范
'hash-value'令牌的使用假定外部脚本已经具有该integrity=属性(来自第三方 CDN 的脚本)。'nonce-value'对于自己的脚本,使用令牌更容易。
此外,Firefox不支持允许外部脚本的“哈希值”,仅允许内部脚本。Safari -也是

是否需要指定此属性的替代方法?

没办法,很遗憾。只有内置脚本<script>...</script>不需要attr,并且如果它们的哈希包含在指令integrity=中,则会自动允许。script-src

我正在研究网站的内容安全策略,特别是严格动态关键字。

小心,Safari 仍然不支持 'strict-dynamic'.

这是我在节点脚本中生成哈希的方式:

常量输入 = `fs.readFileSync("/path/to/index.js");
crypto.createHash("sha256").update(input, 'utf8').digest('base64')

外部脚本的内容在散列之前不需要转换为 UTF8,只需对内联脚本进行转码。
此外,CSP 规范要求所有 ' - ' 字符替换为 ' + ',并且所有 ' _ ' 字符替换为 ' / ' 在哈希中。然后添加“sha256-”前缀。


推荐阅读