关于使用内联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标题中的指令。
请分享你的想法,我们会批评任何反馈!
答案 0 :(得分:0)
可以逐页定义内容安全策略:您可以根据特定需求微调特定页面的策略。
外部文件
我建议首先将所有'非动态'内联样式和脚本移动到外部文件,而不是试图找到一个解决所有问题的解决方案。存在内容安全策略,因为内联脚本不能始终受信任。除了与CSP一起使用外,使用外部文件还有许多其他优点:
<强>沙盒强>
值得关注的另一个“解决方案”是沙盒。如果存在sandbox
指令,则会将该页面视为已加载到具有<iframe>
属性的sandbox
内。
有关沙盒的更多信息,请访问:HTML5 specification。
更多信息
Google开发人员指南:Content Security Policy。
Mozilla开发人员指南:Content Security Policy。
W3C的Web应用安全工作组已经开始研究规范的下一次迭代Content Security Policy Level 3。