关于使用内联JavaScript的思考
我们的开发团队正在开发一个新的Web相关项目.在这个项目中,安全性具有非常高的优先级.但是,在浏览器支持方面实施内容安全策略(CSP)变得非常痛苦和麻烦.
众所周知,CSP是通过阻止所有外部CSS/JavaScript文件并阻止内联脚本执行来引入缓解XSS注入的.指令允许我们定义浏览器将执行的内容和来源的白名单(例如,"自我",域,协议等).
然而,执行内联JavaScript代码是一个完全不同的故事.CSP确实允许使用'unsafe-inline'指令执行内联代码.但是,添加此指令会违背实现CSP的目的.
为了克服这个障碍,我们的团队花了一些时间讨论可行和可行的解决方案.在以下段落中,我们将讨论一些解决方案.欢迎对这些解决方案提出任何建议和反馈.
提案#1:外部文件
在外部文件中提供页面特定代码.此文件将在每个请求中生成,因为它包含动态数据(例如Google Maps密钥,GA跟踪代码段,php-debugbar).以下习语说明了如何在HTML代码中实现此提议.
<html>
<head>
<script src="/generated/external-file.js"></script>
</head>
</html>
Run Code Online (Sandbox Code Playgroud)
优点:客户端将保持透明,因为服务器必须生成文件.
缺点: HTTP是无状态协议,随每个请求而变化的动态数据不能包含在外部文件中(例如php-debugbar).
提案#2:Nonce与CSP一起使用
CSP的第2级通过在CSP响应头中提供随机数来支持内联样式和脚本.下面的习惯用法说明了一个内联脚本,其nonce属性包含动态生成的值.
<script nonce="nm77q3oep8l0ybxmugzewkfyacyma3n3">console.log('Hello world');</script>
Run Code Online (Sandbox Code Playgroud)
为了执行此脚本,nonce需要出现在CSP响应头中.下面的习惯用法说明了如何将此随机数结合到响应头中.
Content-Security-Policy: script-src 'nonce-nm77q3oep8l0ybxmugzewkfyacyma3n3'
Run Code Online (Sandbox Code Playgroud)
出于安全原因,此随机数必须是随机的,并且必须在每个请求上重新生成.
优点:由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>
Run Code Online (Sandbox Code Playgroud)
为了执行此脚本,计算的哈希需要存在于CSP响应头中.以下习语说明了如何将此哈希合并到响应头中.
Content-Security-Policy: script-src 'sha256-9e8a3b5e27971b7309ff6c00f5c80644ffe8e635ce797d7eed8ee23d485a19f2;'
Run Code Online (Sandbox Code Playgroud)
优点:由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>
Run Code Online (Sandbox Code Playgroud)
有关更多信息和示例,请参阅https://mathiasbynens.be/notes/json-dom-csp.
优点:非常安全,因为它不允许脚本标记内的可执行代码.
缺点:此解决方案无法解决每个请求(例如php-debugbar)的动态生成的JavaScript代码.
提案#5:自定义nonce实现
实现自定义nonce解决方案,该解决方案可能会在大多数浏览器支持CSP级别2之前使用.以下内容说明了如何实现此解决方案.
请参阅JSFiddle代码(适用于工作)和Gist与原始代码.
为了执行此脚本,必须在响应头中提供'unsafe-eval'指令.虽然不建议这样做,但这种方法的支持.除了许多像Vue.js这样的框架需要指令才能工作.
以下习语说明了如何将指令合并到响应头中.
Content-Security-Policy: …Run Code Online (Sandbox Code Playgroud) 我想知道如何可以删除特定文件的第一N行有效.
当然,我们可以将完整的文件加载到内存中,然后删除前N行并将完整更改的内容写入文件.
但是,我想知道是否有一种方法可以使这比仅仅加载内存中的所有内容更有效.