当我尝试提交包含 eval() 函数的代码时,所有 Web 编译器(如pythontutor.com、programmr.com、coursera.org自动测试器等)都返回了名称错误。没有在 Web 编译器上实现此功能的原因是什么?
3 回答
eval
功能肯定会被滥用,并且存在安全风险。
代码执行可以在多个级别上受到限制。限制代码功能最强大的工具是 AST 检查和 AST 修改。Python 代码被解析、标记、转换成抽象语法树,最后验证和修改抽象语法树。
Eval 和 exec 可被滥用以在 AST 检查周围偷偷代码。因为在线示例不需要该功能,所以它被简单地省略了。
我将对此进行尝试:
编辑
我不喜欢承认我错了,但在这种情况下,我认为我必须承认。
我要指出的是,无论哪种方式,您都在执行使用代码仍然是正确的,因此您需要真正保护解释器。我仍然相信“如果解释器中存在允许的行为,那么尝试将允许的行为列入黑名单甚至白名单是没有意义的”,因此阻止exec
和eval
帮助只会带来很小的好处。
这是关键点:
那个 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 代码,因此它实现了沙盒以防止执行危险的结构,例如
eval
、exec
、文件 I/O 和大多数模块导入(除了可自定义的模块白名单,例如math
)。
我不会承认我对你应该如何对待exec
andeval
的看法是错误的,但我对网站所有者认为你应该做的事情是错误的(尽管他承认他意识到你也必须沙盒)。
我之前写的:
首先,它几乎绝对与安全无关。默默无闻的安全永远不会奏效,尝试这是一件愚蠢的事情。您不能通过在动态语言中查找对函数的调用来将不良函数列入黑名单。一个简单的模糊示例
import os; while True: os.fork()
将会
import os
while True:
os.__dict__["fork"]()
所以没有保护。我再说一遍:如果解释器中存在允许的操作,那么尝试将允许的操作列入黑名单甚至白名单是没有意义的。这意味着任何 eval
可以到达的东西都可以在没有 eval
的情况下到达,因此阻止不会eval
给您带来安全性。
我认为真正的原因是这些不是典型的 Python 编译器解释器。代码所做的大部分工作都被推送到 Javascript 或其他一些笨拙的平台上。
如果您深入检查过代码,您会发现在编译到字节码时,有些东西会被硬编码,例如名称绑定。当运行像“eval”这样的东西时,你不能只运行内联代码,你必须编译并动态地从作用域中提取东西。在目标语言中支持这种活力是一项具有挑战性的任务,作者可能只是认为不值得这样做。
如果代码在云中编译并在本地执行,则尤其如此:eval
因此必须往返服务器才能工作!这不是建议的行动方案。
这是我的猜测,虽然我不知道这些东西是如何实现的。