内容安全策略(CSP)-如何安全地使用unsafe-eval?

31

我们使用以下CSP头:

default-src 'self' *.ourdomain.com; script-src 'self' *.ourdomain.com 'sha256-[...]' 'unsafe-eval'; 
connect-src 'self' *.ourdomain.com; 
style-src 'unsafe-inline' * 'self' data:; font-src *; 
img-src * 'self' data:
我们的安全团队建议不使用unsafe-eval。
我的问题是:只要我们使用sha256-[...]来限制任何我们没有部署自己的脚本,仍然保持CSP头中的unsafe-eval存在什么安全风险?在什么情况下这仍会使我们暴露于跨站点攻击?
2个回答

36

因为eval是绝对不安全的。在任何语言中,eval都意味着“接受这个字符串并执行它作为代码”。当然,你可能正在以半安全的方式使用eval,但只要允许它存在,就意味着“任何人都可以在我的应用程序中执行任意代码”。

2022修改:下面的部分未经时间检验,像WASM之类的东西需要unsafe-eval。仍然有很多前端框架需要unsafe-eval

我认为没有理由使用eval。向我展示一个实际有用的代码需要使用eval的情形,我敢打赌我可以重写该代码而不使用eval或将其声明为不可能安全的代码。

禁止内联脚本只是其中一部分内容,特别是如果您使用jquery。

问答题:这段代码会触发内联脚本违规还是eval违规?

$('body').html('<script>alert(1)</script>')

你可能会感到惊讶。

剧透:

这是eval(在撰写本文时)


10
原因在于性能。构建一个和编译代码一样快的解释器几乎是不可能的。使用 eval() 在代码依赖于某些运行时数据的情况下可以提高代码的速度。举个更具体的例子,考虑一个网站,用户提供数据的 URL 和一个任意表达式用于操作这些数据。该表达式需要被执行数百万次。使用解释方式执行(例如将表达式 "a.b.c" 转换为数组 ['a','b','c'],并循环访问子对象)显然比 x=eval('(a) => a.b.c') 然后调用 x(a) 更慢。 - Yuri Astrakhan
3
@yurik 是的,性能绝对是一个原因。我没有任何数据来支持它,但我感觉在许多情况下性能提升并不会有意义。人们过去常常使用eval来代替解析JSON,但很多人认为这种权衡并不值得。 - oreoshake
3
展示一个需要使用 eval 的案例,我敢打赌我可以重写这段代码而不使用 eval 或者将其声明为不可能被攻击的代码: function check() { try { eval("class = {}"); } catch (e) { return false; } return true; } - Julius Žaromskis
1
无论我们如何修改自己的脚本、jQuery 和其他第三方库,仍然会不时触发一个被 CSP 阻止的 eval。如果不重写别人的代码(这样使用这些库就没有意义了),我们只能束手无策,只好在定义中添加 unsafe-eval - IncredibleHat
1
感谢@XRBtoTheMOON提醒,我已更新了剧透。 - oreoshake
显示剩余9条评论

5
安全风险在于它不保护您自己的代码,因为使用了"eval"。
如果您在自己的代码中使用"eval",应该思考为什么会这样。是否有更安全的替代方案可供选择?
请参见此处(虚构)关于攻击者如何注入代码的示例。当然,这是否能够对您的网站进行操作,很大程度上取决于您的代码。
总之,几乎总是有替代方案可以使用,而不是使用"eval"。

5
我可以请你确认一下吗?我们使用KendoUI,它在模板中使用eval()。 - Old fart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接