我想要一种简单的方法在Python中执行"计算器API".
现在,我并不关心计算器将支持的确切功能集.
我希望它接收一个字符串,"1+1"并在我们的例子中返回一个包含结果的字符串"2".
有没有办法让eval这种东西安全?
首先,我会这样做
env = {}
env["locals"] = None
env["globals"] = None
env["__name__"] = None
env["__file__"] = None
env["__builtins__"] = None
eval(users_str, env)
Run Code Online (Sandbox Code Playgroud)
这样调用者就不会搞乱我的局部变量(或看到它们).
但我相信我在这里监督很多.
eval安全问题是否可以解决,或者是否存在太多微小的细节以使其正常工作?
我们都知道这eval很危险,即使你隐藏了危险的函数,因为你可以使用Python的内省功能深入挖掘并重新提取它们.例如,即使您删除__builtins__,也可以使用它来检索它们
[c for c in ().__class__.__base__.__subclasses__()
if c.__name__ == 'catch_warnings'][0]()._module.__builtins__
Run Code Online (Sandbox Code Playgroud)
但是,我见过的每个例子都使用属性访问.如果我禁用所有内置函数并禁用属性访问(通过使用Python令牌化程序对输入进行标记,并在具有属性访问令牌时拒绝它),该怎么办?
在你问之前,不,对于我的用例,我不需要其中任何一个,所以它不会太瘫痪.
我想要做的是让SymPy的同情功能更安全.目前,它对输入进行了标记,对其进行了一些转换,并在命名空间中对其进行了演绎.但它不安全,因为它允许属性访问(即使它真的不需要它).
如果我使用eval()评估Python字符串,并且有一个类如下:
class Foo(object):
a = 3
def bar(self, x): return x + a
Run Code Online (Sandbox Code Playgroud)
如果我不信任字符串会有什么安全风险?特别是:
eval(string, {"f": Foo()}, {})不安全的?也就是说,你可以从Foo实例到达os或sys或者不安全的东西吗?eval(string, {}, {})不安全的?也就是说,我可以完全从内置像len和list到达os或sys吗?有一些不安全的字符串,如"[0]*100000000",我不在乎,因为在最坏的情况下,他们会减慢/停止程序.我主要关心的是保护程序外部的用户数据.
显然,eval(string)在大多数情况下,没有自定义词典是不安全的.