内联JavaScript与CSP Level 1

时间:2017-04-10 15:13:08

标签: javascript json http inline content-security-policy

关于使用内联JavaScript的想法

我们的开发团队正在开发一个与Web相关的新项目。在这个项目中,安全性具有非常高的优先级。但是,在浏览器支持方面实施内容安全策略(CSP)变得非常痛苦和麻烦。

众所周知,CSP是通过阻止所有外部CSS / JavaScript文件并阻止内联脚本执行来引入缓解XSS注入的。指令允许我们定义浏览器将执行的内容和来源的白名单(例如' self',域,协议等)。

然而,执行内联JavaScript代码是一个完全不同的故事。 CSP确实允许使用' unsafe-inline'执行内联代码。指示。但是,添加此指令会违背实现CSP的目的。

为了克服这个障碍,我们的团队花了一些时间讨论可行和可行的解决方案。 在以下段落中,我们将讨论一些解决方案。欢迎对这些解决方案提出任何建议和反馈。

提案#1:外部文件

在外部文件中提供页面特定代码。此文件将在每个请求中生成,因为它包含动态数据(例如Google Maps密钥,GA跟踪代码段,php-debugbar)。 以下习语说明了如何在HTML代码中实现此提议。

<html>
    <head>
        <script src="/generated/external-file.js"></script>
    </head>
</html>

优点:客户端将保持透明,因为服务器必须生成文件。

缺点: HTTP是无状态协议,随每个请求而变化的动态数据不能包含在外部文件中(例如php-debugbar)。

提案#2:Nonce与CSP一起

CSP的第2级通过在CSP响应头中提供随机数来支持内联样式和脚本。 下面的习惯用法说明了一个内联脚本,其nonce属性包含动态生成的值。

<script nonce="nm77q3oep8l0ybxmugzewkfyacyma3n3">console.log('Hello world');</script>

为了执行此脚本,nonce需要出现在CSP响应头中。 下面的习惯用法说明了如何将此nonce合并到响应头中。

Content-Security-Policy: script-src 'nonce-nm77q3oep8l0ybxmugzewkfyacyma3n3'

出于安全原因,此随机数必须是随机的,并且必须在每次请求时重新生成。

优点:由CSP第2级支持。

缺点:浏览器支持是一个问题(75%的浏览器实施CSP级别2,约会时间为2017年4月10日(http://caniuse.com/#feat=contentsecuritypolicy2)。

提案#3:与CSP一起散列

CSP的第2级通过散列这些元素的内容并在CSP响应头中提供此哈希来支持内联样式和脚本。 下面的习惯用法说明了一个内联脚本,其内容将生成以下SHA-256哈希:9e8a3b5e27971b7309ff6c00f5c80644ffe8e635ce797d7eed8ee23d485a19f2

<script>console.log('Hello world');</script>

为了执行此脚本,计算的哈希需要存在于CSP响应头中。 以下习惯用法说明了如何将此哈希值合并到响应头中。

Content-Security-Policy: script-src 'sha256-9e8a3b5e27971b7309ff6c00f5c80644ffe8e635ce797d7eed8ee23d485a19f2;'

优点:受CSP第2级支持,并允许通过使用HTTP加速器来缓存页面。

缺点:浏览器支持是一个问题(75%的浏览器实施CSP级别2,约会时间为2017年4月10日(http://caniuse.com/#feat=contentsecuritypolicy2)。

提案#4:JSON

CSP仅禁止包含可执行JavaScript代码的脚本元素,简而言之,这意味着允许脚本元素中的配置数据。 以下习语说明了包含JSON数据的脚本元素。

<script type="application/json">
{
    "googleMapsKey": "v1zs9Bc10hMZ073S14gy",
    "analyticsProperty": "UA-192348"
}
</script>

有关更多信息和示例,请参阅https://mathiasbynens.be/notes/json-dom-csp

优点:非常安全,因为它不允许脚本标记内的可执行代码。

缺点:此解决方案无法解决每个请求(例如php-debugbar)的动态生成的JavaScript代码。

提案#5:自定义nonce实现

实施自定义nonce解决方案,可在大多数浏览器支持CSP级别2之前使用。 以下习语说明了如何实施此解决方案。

使用原始代码查看JSFiddle code(适应工作)和/或Gist

为了执行此脚本,&#39; unsafe-eval&#39;必须在响应头中提供指令。虽然不建议这样做,但这种方法的支持。除了Vue.js require这个指令之外的许多框架。

以下习语说明了如何将指令合并到响应头中。

Content-Security-Policy: script-src 'unsafe-eval'

优点:支持CSP级别1,当大多数浏览器支持CSP级别2时,可以轻松适应提案#2而不会有太多麻烦。

缺点:自定义实施必须经过全面测试,并且需要&#34; unsafe-eval&#34; CSP标题中的指令。

请分享你的想法,我们会批评任何反馈!

1 个答案:

答案 0 :(得分:0)

可以逐页定义内容安全策略:您可以根据特定需求微调特定页面的策略。

外部文件

我建议首先将所有'非动态'内联样式和脚本移动到外部文件,而不是试图找到一个解决所有问题的解决方案。存在内容安全策略,因为内联脚本不能始终受信任。除了与CSP一起使用外,使用外部文件还有许多其他优点:

  • 外部资源更易于浏览器缓存;
  • 对开发者来说更​​容易理解;
  • 并有助于汇编和缩小。

<强>沙盒

值得关注的另一个“解决方案”是沙盒。如果存在sandbox指令,则会将该页面视为已加载到具有<iframe>属性的sandbox内。

有关沙盒的更多信息,请访问:HTML5 specification

更多信息

Google开发人员指南:Content Security Policy

Mozilla开发人员指南:Content Security Policy

W3C的Web应用安全工作组已经开始研究规范的下一次迭代Content Security Policy Level 3