【发布时间】:2019-10-17 09:15:55
【问题描述】:
我正在将 CSP 标头添加到一个网站,该网站还有很长的路要走才能采用严格的政策。有很多内联脚本,所以我使用 nonce- 来允许特定的内联脚本。我发现它不适用于带有 src 的脚本标签的 onload 属性。这是一个例子:
// header:
Content-Security-Policy: script-src self https: 'nonce-d3adbe3fed'
<script async defer src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" nonce="d3adbe3fed" onload="console.log('onload', _.VERSION)"></script>
完整的工作演示在https://brave-pasteur-0d438b.netlify.com/
Chrome 出现以下错误:
Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src self https: 'nonce-d3adbe3fed'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
该消息表明应该可以使用 nonce 启用内联事件处理程序,但据我所知,nonce 仅适用于内联脚本。
这只是一个演示,但用例是加载跟踪库的异步/延迟跟踪脚本,然后在 onload 处理程序中对加载的库进行跟踪调用。
是否可以在onload 或其他事件处理程序属性上使用随机数,或者我需要更改我的实现吗?使用script-src 'unsafe-inline' 或script-src-attr 'unsafe-inline' 不是一种选择,因为这些是我特别试图解决的漏洞。并且将onload 处理程序的内容放入脚本标记之后的单独脚本中也不是一种选择,因为脚本是async deferred,并且需要保持这种方式。
【问题讨论】:
-
错误信息具有误导性。请参阅github.com/w3c/webappsec/issues/468 并查看stackoverflow.com/questions/50842033/… 的评论。尽管该错误消息似乎暗示了什么,但在 CSP2 和当前浏览器中,只有元素内容是“不可确定的”——而事件处理程序属性则不是。
-
但另请参阅stackoverflow.com/a/44609372/441757 的答案。 CSP3 添加了一个新的
unsafe-hashes表达式以允许特定的内联脚本/样式。见w3c.github.io/webappsec-csp/#unsafe-hashes-usage。有关详细信息,请参阅docs.google.com/document/d/… 上的解释器:'unsafe-hashes'、'unsafe-inline-attributes' 和 CSP 指令版本控制文档。但unsafe-hashes功能尚未在除 Chrome 之外的任何浏览器中提供:chromestatus.com/feature/5867082285580288 -
请注意:CSP2 规范中的语言更清楚地说明了哪些 nonce 可以和不能一起使用;它有一个明确标题为 Nonce 用于脚本元素 w3.org/TR/CSP2/#script-src-nonce-usage 的特定部分,但没有类似的部分标题为“事件处理程序的 Nonce 用法”(或类似)。 (一般来说,当试图弄清楚 CSP 要求和行为时,我经常发现(旧的)w3.org/TR/CSP2 规范中的语言以比当前规范更加开发人员友好(相对于浏览器实施者友好)的方式声明它们在w3c.github.io/webappsec-csp 确实)
-
对未来读者的另一个注意事项:哈希值也不适用于事件处理程序。因此,允许特定内联事件处理程序的唯一方法是允许所有事件处理程序。在我看来,这是当前 CSP 实施的重大失败。
-
使哈希值在事件处理程序上起作用是新的 CSP3
unsafe-hashes表达式的用途。尽管正如我在之前的评论中提到的,unsafe-hashes支持尚未在除 Chrome chromestatus.com/feature/5867082285580288 之外的任何浏览器中提供,但这种情况下的失败至少不是由于规范作者忽略为其定义机制——相反,其他浏览器项目未能优先考虑实施它。也许部分原因是,他们只是没有听到足够多的开发人员认为他们应该优先考虑它。
标签: javascript content-security-policy nonce