为什么使用 JavaScript eval 函数是个坏主意?

IT技术 javascript security eval
2020-12-20 23:30:01

eval 函数是一种强大而简单的动态生成代码的方法,那么有什么注意事项呢?

6个回答
  1. 不正确使用eval 会打开您的代码进行注入攻击

  2. 调试可能更具挑战性(没有行号等)

  3. eval 代码执行速度较慢(没有机会编译/缓存 eval 代码)

编辑:正如@Jeff Walden 在评论中指出的那样,今天的 #3 不如 2008 年那么真实。然而,虽然可能会发生一些编译脚本的缓存,但这将仅限于未经修改而重复 eval 的脚本。更可能的情况是您正在评估每次都经过轻微修改的脚本,因此无法缓存。我们只是说一些 eval'd 代码执行得更慢。

@TamilVendhan 当然可以设置断点。您可以通过将debugger;语句添加到源代码来访问 Chrome 为您的评估代码创建的虚拟文件这将停止在该行上执行您的程序。然后,您可以添加调试断点,就像它只是另一个 JS 文件一样。
2021-02-12 23:30:01
一般来说,如果不是大多数函数调用,#1 在很多情况下都是正确的。eval() 不应该被有经验的程序员挑出来避免,仅仅因为没有经验的程序员滥用它。然而,有经验的程序员通常在他们的代码中有更好的架构,并且由于这种更好的架构,很少需要甚至考虑 eval()。
2021-02-20 23:30:01
@JeffWalden,很棒的评论。我已经更新了我的帖子,虽然我意识到你发帖已经一年了。Xnzo72,如果您在某种程度上限定了您的评论(就像杰夫所做的那样),那么我可能会同意您的看法。Jeff 指出了关键:“多次对同一个字符串求值可以避免解析开销”。事实上,你错了;#3 适用于许多场景。
2021-03-04 23:30:01
@EduardoMolteni,我们不在乎(实际上也不能阻止)用户在他们自己的浏览器中执行 js。我们试图避免的攻击是当用户提供的值被保存,然后被放入 javascript 和 eval'd 时。例如,我可能将我的用户名设置为:badHackerGuy'); doMaliciousThings();如果您使用我的用户名,将其连接到某个脚本中并在其他人的浏览器中对其进行评估,那么我可以在他们的机器上运行我想要的任何 javascript(例如,强制他们为我的帖子 +1,将他们的数据发布到我的服务器等)
2021-03-05 23:30:01
@Prestaul:既然假定的攻击者可以使用任何开发人员工具来更改客户端中的 JavaScript,那么您为什么说 Eval() 会打开您的代码以进行注入攻击?不是已经开了吗?(我当然是在谈论客户端 JavaScript)
2021-03-06 23:30:01

eval 并不总是邪恶的。有时它是完全合适的。

然而, eval 目前和历史上被那些不知道自己在做什么的人过度使用。不幸的是,这包括编写 JavaScript 教程的人,在某些情况下,这确实会产生安全后果——或者更常见的是简单的错误。所以我们能做的越多,对 eval 打一个问号就越好。任何时候使用 eval 时,您都需要仔细检查您在做什么,因为您可能会以一种更好、更安全、更清洁的方式来做。

举一个非常典型的例子,使用存储在变量“potato”中的 id 设置元素的颜色:

eval('document.' + potato + '.style.color = "red"');

如果上述代码的作者对 JavaScript 对象的工作原理有所了解,他们就会意识到可以使用方括号代替文字点名称,从而无需使用 eval:

document[potato].style.color = 'red';

...这更容易阅读,而且潜在的错误更少。

(但是,/真正/知道自己在做什么的人会说:

document.getElementById(potato).style.color = 'red';

这比直接从文档对象中访问 DOM 元素的狡猾老技巧更可靠。)

嗯,当我第一次学习 JavaScript 时,我猜我很幸运。我总是使用“document.getElementById”来访问 DOM;具有讽刺意味的是,我当时才这样做,因为我不知道对象在 JavaScript 中是如何工作的 ;-)
2021-02-20 23:30:01
同意。有时 eval 是可以的,例如对于来自网络服务的 JSON 响应
2021-02-20 23:30:01
@schoetbi:你不应该使用JSON.parse()代替eval()JSON 吗?
2021-02-23 23:30:01
@bobince code.google.com/p/json-sans-eval适用于所有浏览器,github.com/douglascrockford/JSON-js也是如此Doug Crockford 的 json2.js 确实在内部使用了 eval,但带有检查。此外,它与内置浏览器对 JSON 的支持向前兼容。
2021-03-02 23:30:01
@bobince 有一种叫做功能检测和 polyfills 的东西来处理丢失的 JSON 库和其他东西(看看modernizr.com
2021-03-04 23:30:01

我相信这是因为它可以从字符串中执行任何 JavaScript 函数。使用它可以让人们更容易地将恶意代码注入到应用程序中。

我不相信这个论点,因为将流氓代码注入到 Javascript 应用程序中已经很容易了。我们有浏览器控制台、脚本扩展等......发送到客户端的每一段代码都是客户端执行的可选代码。
2021-02-10 23:30:01
关键是我更容易将代码注入您的浏览器。假设您在查询字符串上使用 eval。如果我诱使您点击一个链接到该站点并附有我的查询字符串,那么我现在已经在浏览器的完全许可下在您的机器上执行了我的代码。我想记录您在该网站上键入的所有内容并将其发送给我?完成了,没有办法阻止我,因为当 eval 执行时,浏览器会给它最高权限。
2021-02-10 23:30:01
真正的替代方法是编写不需要它的代码。Crockford 对此进行了详细介绍,如果您需要使用它,他几乎说这是一个程序设计缺陷,需要重新设计。事实上,我也同意他的看法。JS 的所有缺陷都非常灵活,并允许很大的空间使其灵活。
2021-02-18 23:30:01
那还有什么办法呢?
2021-03-01 23:30:01
不是的,大部分框架都有解析JSON的方法,如果你没有使用框架,可以使用JSON.parse()。大多数浏览器都支持它,如果你真的很紧张,你可以很容易地为 JSON 编写解析器。
2021-03-02 23:30:01

想到两点:

  1. 安全性(但只要您自己生成要评估的字符串,这可能不是问题)

  2. 性能:直到要执行的代码未知,才能优化。(关于 javascript 和性能,当然是Steve Yegge 的演讲

@PaulBrewczynski,当用户 A 保存他要使用的那部分代码eval然后在用户 B 的浏览器上运行那一小段代码时,就会出现安全问题
2021-02-18 23:30:01
如果客户无论如何都可以用我们的代码做他/她想做的任何事情,为什么安全性是一个问题?油猴?
2021-03-01 23:30:01

如果您传递 eval 用户输入,这通常只是一个问题。

这意味着只是一些简单的页面计算不会损害任何东西。很高兴知道。
2021-02-10 23:30:01