为什么在JavaScript之外使用eval不是一个好主意?

huangapple go评论67阅读模式
英文:

Why isn't eval a bad idea outside of JavaScript?

问题

在JavaScript中,eval 被认为是一个不好的主意,主要是因为它会使您的代码容易受到注入攻击的威胁。引用这条评论

我们试图避免的攻击是用户提供的值被保存,然后稍后被放入JavaScript并进行评估。例如,我可以将我的用户名设置为:badHackerGuy'); doMaliciousThings();,如果您将我的用户名连接到某些脚本中并在其他人的浏览器中进行评估,那么我可以在他们的机器上运行任何JavaScript代码(例如,强制他们给我的帖子点赞,将他们的数据发布到我的服务器等)。

但为什么这个问题仅限于JavaScript呢?是的,JavaScript是唯一在浏览器上运行的语言,但除了浏览器之外,还有其他上下文,你也希望避免注入攻击。

(这部分与我的实际问题无关,但人们谈论 [元编程的极限和强大之处。eval 允许您进行元编程,听起来注入攻击问题是唯一的重大缺点。为什么被认为这个缺点超过了优点?)

英文:

In JavaScript, eval is considered to be a bad idea mainly because it opens up your code to injection attacks. To quote this comment:

> The attacks we are trying to avoid are when user provided values get saved, then later placed into javascript and eval'd. For example, I might set my username to: badHackerGuy'); doMaliciousThings(); and if you take my username, concat it into some script and eval it in other people's browsers then I can run any javascript I want on their machines (e.g. force them to +1 my posts, post their data to my server, etc.)

But why is this problem limited to JavaScript? Yes, JavaScript is the only language that runs on browsers, but there are contexts other than browsers where you want to avoid injection attacks.

(This part is tangential to my actual question, but people talk about the extreme, awesome power of metaprogramming. eval allows you to do metaprogramming and it sounds like the injection attack issue is the only big downside. Why is considered to be clear that the downside outweighs the upside?)

答案1

得分: 3

我只能代表Lisp说,答案是你的假设是错误的:在Lisp代码中,eval几乎总是一个极其糟糕的想法。

如果你在代码中看到(eval x),除非你详细了解x是什么,否则你不知道这是什么:它几乎可以做任何(几乎)Lisp系统能做的事情。如果x包含或可能包含不受信任的数据,那么这只是一个非常非常糟糕的想法,理由非常明显。

你可以通过编写一种检查x是否安全的遍历器来使其安全。但是...这个遍历器与对Lisp的安全子集的求值器几乎是一样的:只需使用它!

eval在Lisp中有用,所以它存在于语言中是好的,但你需要它的情况很少。确实有一些情况,你希望能够评估任意的Lisp源代码,比如编写开发环境,但它们非常非常罕见。

特别要注意不要在Lisp中将eval与元编程混淆。在Lisp中,元编程的传统方法(我说“传统”是因为Scheme在某种程度上不太像这样)根植于两个想法:

  1. 语言的源代码可以在语言本身中表示为一种适当低承诺的数据结构。
  2. 你可以编写称为宏的函数,它们将从此源代码表示的实例映射到其他实例。

当然,还有更多内容,但要注意:这不需要eval

英文:

I can only speak for Lisp but the answer is that your assumption is false: eval is, almost always, an extremely bad idea in Lisp code.

If you see (eval x) in a piece of code then unless you have detailed knowledge of what x is, you have no idea what this does: it can do anything (almost) that the Lisp system can do. If x contains, or may contain, untrusted data, then that's just a really, really bad idea for very obvious reasons.

You could make this safe by writing some kind of walker which looks at x and checks it is safe. But ... that walker is within epsilon of being an evaluator for your safe subset of Lisp: just use it, instead!

eval has uses in Lisp, so it is good that it is in the language, but the cases where you need it are few and far between: there are cases where you wish to be able to evaluate arbitrary Lisp source code, such as writing a development environment, but they're very, very rare.

In particular do not conflate (in Lisp) eval with metaprogramming. In Lisp the traditional approach to metaprogramming (I say 'traditional' because Scheme is arguably not, quite, like this) is rooted in two ideas:

  1. the source code of the language is representable as a suitably low-commitment data structure in the language itself;
  2. You can write functions, called macros, which will map from instances of this source code representation to other instances.

There is much more to it than this of course, but note: this does not require eval.

huangapple
  • 本文由 发表于 2023年3月12日 13:15:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75711178.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定