使用ast和白名单制作python';安全吗?
嗯。我和您永远不应该在不受信任的数据上使用python的使用ast和白名单制作python';安全吗?,python,security,parsing,eval,Python,Security,Parsing,Eval,嗯。我和您永远不应该在不受信任的数据上使用python的eval()。我并不比世界上其他人聪明,甚至不应该尝试这个。但是无论如何,我要去 我的基本问题是,我希望编写一个小型计算器计算器程序,使用python语法的一个子集来接受不可信的输入。我知道:使用或编写解析器,我们就可以开始了。将全局和局部传递给eval()不会起作用 我所看到的(并且一直对其持怀疑态度的)所有方法都试图列举罪恶。在这里,我试图枚举好的——获取一个AST,只允许几个节点类型,然后验证所有调用都是对一组白名单函数之一的调用。下
eval()
。我并不比世界上其他人聪明,甚至不应该尝试这个。但是无论如何,我要去
我的基本问题是,我希望编写一个小型计算器计算器程序,使用python语法的一个子集来接受不可信的输入。我知道:使用或编写解析器,我们就可以开始了。将全局和局部传递给eval()
不会起作用
我所看到的(并且一直对其持怀疑态度的)所有方法都试图列举罪恶。在这里,我试图枚举好的——获取一个AST,只允许几个节点类型,然后验证所有调用都是对一组白名单函数之一的调用。下面是一个小型实现(和):
导入ast
输入数学
安全系数={
“exp”:math.exp,
}
安全节点=集合(
(ast.Expression,
ast.Num,
打电话,
姓,
最后加载,
ast.BinOp,
最后加上,
东区分区办事处,
马斯特,
行政司)
)
类CleansingNodeVisitor(ast.NodeVisitor):
def通用_访问(自身、节点):
如果类型(节点)不在安全节点中:
引发异常(“%s”不在安全节点“%type(node))
超级(清除节点设备,自我)。一般访问(节点)
def访问呼叫(自我,呼叫):
如果call.func.id不在SAFE\u FX中:
引发异常(“未知函数:%s”%call.func.id)
定义我的安全评估:
tree=ast.parse(s,mode='eval')
cnv=清洁节点设备()
cnv.参观(树)
编译=编译(树,s,“eval”)
返回(评估(已编译、安全)
因此,my_safe_eval('2*(4+exp(1.3))
有效,而my_safe_eval('[].\uu class\uuuuuuu')
技巧和my_safe_eval('open(“/something/evil”)
同样被禁止——但不禁止\uu内置的东西或\uuuuuu本地的东西
我。。。我认为这是可行的。我疯了吗?Zope有一个东西叫做,你可能想检查它,至少是为了验证你的方法或者可能重用他们的代码。它是可配置和可重用的
这里有一个类似的问题。试试看,这似乎是你需要的东西。
除此之外,还有一条RestrictedPython看起来很整洁,但伙计,它太大了。我真的希望只安全地支持python语法的一小部分,并且只支持计算表达式和有限的函数调用集。我不认为沙盒python是我真正想要的。不能完全说出原因。太好了,但是如何处理而为True:例如pass
?我也在看,非常有兴趣听到人们的输入。您是否对代码进行了基准测试?你试过所有的漏洞了吗?看到有人这么做真是太激动了!无法利用asteval,因为它非常有限,并且在AST级别删除。我不得不放弃我的项目,因为它是有限的。我使用spydermonkey和pyv8。。但在两种不同语言之间的上下文切换中,这是一个过载。因此,我要么使用pypy,要么只是删除eval功能,用简单的解析器替换它们——这是最好的决定。大多数情况下,你不需要图灵完整性……这与这个非常相似,也可以看到这个:这只是另一个例子,因为我实际上就是同一个Nate Vack:)