【问题标题】:Why doesn't eval() work in web compilers?为什么 eval() 在 Web 编译器中不起作用?
【发布时间】:2013-09-22 17:50:32
【问题描述】:

当我尝试提交包含 eval() 函数的代码时,所有 Web 编译器(如 pythontutor.comprogrammr.comcoursera.org autotester 等中的编译器)都返回了名称错误。 Web 编译器没有实现这个功能的原因是什么?

【问题讨论】:

  • 有趣的问题 .. 因为那些无论如何都允许评估用户输入。看起来 eval 可以像其他代码评估一样多(或少)得到保护。
  • 这似乎是上述引擎的限制evalideone 上按预期工作。我怀疑那些其他工具简单地缺乏实现eval 的合理方法,因此禁止它(我在另一条评论中严厉地谈到了设计)。我认为没有额外的固有危险,因为在这两种情况下,要执行的代码都来自(远程)用户。
  • 另一方面,也许他们只是想阻止使用eval :D

标签: python compiler-errors eval


【解决方案1】:

eval 函数肯定会被滥用并且存在安全风险。

【讨论】:

  • 我想它会使代码更难过滤,这允许用户直接执行通常会被服务器上的规则从提交的脚本中删除的代码。
  • @StephanHeijl 然后它们是一开始就被打破的方法:> 我想一些没有良好基础的方法可以“过滤”这样的功能以试图“更安全”,但我认为它们是如果这是他们的策略,那根本就存在缺陷。
  • @unutbu 如果在线引擎无论如何都允许用户输入,那么它是否在eval 中有什么区别?
  • @StephanHeijl 我看不到会产生什么额外安全风险。假设如果可以执行任意代码,那么如果它在eval 中又有什么关系呢?实现支持(或缺乏)与任何用户提供的评估代码的基本安全问题正交。
【解决方案2】:

可以在多个级别上限制代码执行。限制代码功能最强大的工具是 AST 检查和 AST 修改。 Python代码被解析、标记、转换成抽象语法树,最后对抽象语法树进行验证和修改。

Eval 和 exec 可被滥用以在 AST 检查周围偷偷代码。因为在线示例不需要该功能,所以直接省略了。

【讨论】:

  • 对为什么某些 [white-list?] 实现可能会拒绝该构造的合理解释。 (尽管似乎可以对提供给 eval/exec 的代码应用相同的规则。实现这样的钩子/支持可能“不值得我们花时间”。)
  • Tiran,您能否提供一些资源以获取有关解析、标记化、无语法转换和 AST 检查的信息?
【解决方案3】:

我会试一试:

编辑

我不喜欢承认自己错了,但在这种情况下,我认为我必须承认。

我会指出,无论哪种方式,您都在执行使用代码,这仍然是正确的,因此您需要真正保护解释器。我仍然相信“如果解释器中存在允许的操作,那么尝试将这些操作列入黑名单甚至白名单都没有任何意义”,因此阻止 execeval 只会带来很小的好处。

这里是重点:

那个 Python Tutor 的创建者执行了从外部交给他们的代码。尽管阻止了很多事情,包括exec,因为它们允许执行外部代码,但我发现了一个漏洞。目前我只导入了一个阻塞的模块,但是阅读源代码这也可以让我做无限的 IO。

进一步编辑:我已经联系了 Python Tutor 的所有者,他说他知道这一点,据说保护也存在于较低级别。所以这不是一个漏洞,但这主要是因为有“较低级别”的保护。这就是您要防范攻击的方式,而不是黑名单。

进一步, 进一步编辑:我已经关闭了 Python Tutor,尽管该网站似乎又恢复了(没有功能,只是恢复了),因为我是看看我是否可以用我的这个漏洞读/写任何东西(应所有者 Philip Guo 的要求)。看来我至少可以破坏网站:/。对不起,那是个意外。不过,它确实证明了运行不受信任的代码是危险的,这就是我一直在说的。

但是,问题是关于意图,而不是关于阻止 exec 是否真的有影响。

阅读http://pgbovine.net/projects/pubs/guo-sigcse-preprint_2012-11-13.pdf,即

由于后端运行来自 Web 的不受信任的 Python 代码,因此它实施沙盒以防止执行危险的构造,例如 evalexec、文件 I/O 和大多数模块导入(可自定义的白名单除外) math等模块。

我不会承认我对您应该如何对待execeval 有错误,但我对网站的所有者 的想法是错误的你应该这样做(尽管他承认你必须沙盒)。


我之前写的:

首先,它几乎绝对与安全无关。 默默无闻的安全永远不会奏效,尝试这样做很愚蠢。您不能通过在动态语言中查找对函数的调用来将不良函数列入黑名单。一个简单的模糊示例

import os; while True: os.fork()

import os
while True:
    os.__dict__["fork"]()

所以没有保护。我再说一遍:如果解释器中存在允许的操作,没有任何意义试图将允许的操作列入黑名单,甚至白名单。这意味着 anything eval 可以到达 没有 eval,因此阻止 eval 会给您no安全性。 p>


我认为真正的原因是这些不是典型的 Python 编译器解释器。代码所做的大部分工作都被推送到 Javascript 或其他一些笨拙的平台上。

如果您深入检查过代码,您会发现在编译到字节码时,有些东西会被硬编码,例如名称绑定。当运行像“eval”这样的东西时,你不能只运行内联代码,你必须编译并动态地从作用域中提取东西。在目标语言中支持这种活力是一项具有挑战性的任务,作者可能只是认为不值得这样做。

如果代码在云中编译并在本地执行,则尤其如此:eval 因此必须往返于服务器才能工作!这不是建议的行动方案。

这是我的猜测,虽然我不知道这些东西实际上是如何实现的。

【讨论】:

  • 你错了。有很多方法可以阻止有害功能。例如,有限的解释器可以阻止所有未列入白名单的功能。沙盒解释器可以使用 AST 检查来限制范围和功能。您甚至可以在操作系统级别阻止 sys 调用,例如SECCOMP。
  • 要么通过eval屏蔽危险,在这种情况下没有理由屏蔽eval,或者它是无效的。您所说的大部分内容都适用于通用代码和eval,尽管我不确定您所说的“块函数”是什么意思。这就是我要表达的观点,我已经在帖子中澄清了。
  • 当然你可以修复eval。但这是更多的工作和额外的安全风险。当在线课程不需要该功能时,为什么要冒险?
  • 查看我的更新作为对该问题的回应。关键是,如果您正在执行任意代码,则 nothing 您可以使用 execeval 做这些您不能没有的事情,句号。因此,阻止 execeval 会带来没有安全优势。
猜你喜欢
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-16
  • 2017-07-16
  • 1970-01-01
相关资源
最近更新 更多