【发布时间】:2012-05-26 12:38:31
【问题描述】:
原问题:
Executing mathematical user code on a python web server, what is the simplest secure way?
- 我希望能够在 python 网络服务器上运行用户提交的代码。代码本质上是简单的和数学的。
由于需要这么小的 Python 子集,我目前的方法是通过遍历 Python 的抽象语法树来将允许的语法列入白名单。函数和名称得到特殊处理;只允许明确列入白名单的函数,并且只允许未使用的名称。
import ast
allowed_functions = set([
#math library
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh',
'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf',
'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod',
'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp',
'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians',
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc',
#builtins
'abs', 'max', 'min', 'range', 'xrange'
])
allowed_node_types = set([
#Meta
'Module', 'Assign', 'Expr',
#Control
'For', 'If', 'Else',
#Data
'Store', 'Load', 'AugAssign', 'Subscript',
#Datatypes
'Num', 'Tuple', 'List',
#Operations
'BinOp', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'Compare'
])
safe_names = set([
'True', 'False', 'None'
])
class SyntaxChecker(ast.NodeVisitor):
def check(self, syntax):
tree = ast.parse(syntax)
self.visit(tree)
def visit_Call(self, node):
if node.func.id not in allowed_functions:
raise SyntaxError("%s is not an allowed function!"%node.func.id)
else:
ast.NodeVisitor.generic_visit(self, node)
def visit_Name(self, node):
try:
eval(node.id)
except NameError:
ast.NodeVisitor.generic_visit(self, node)
else:
if node.id not in safe_names and node.id not in allowed_functions:
raise SyntaxError("%s is a reserved name!"%node.id)
else:
ast.NodeVisitor.generic_visit(self, node)
def generic_visit(self, node):
if type(node).__name__ not in allowed_node_types:
raise SyntaxError("%s is not allowed!"%type(node).__name__)
else:
ast.NodeVisitor.generic_visit(self, node)
if __name__ == '__main__':
x = SyntaxChecker()
while True:
try:
x.check(raw_input())
except Exception as e:
print e
这似乎接受了所需的语法,但我对编程相当陌生,可能会遗漏许多巨大的安全漏洞。
所以我的问题是:这是否安全,是否有更好的方法,还有我应该采取的其他预防措施吗?
【问题讨论】:
-
对我来说,我看起来很安全......但请注意:脚本中的名称有些泄漏到沙箱中。如果我测试
x它说 x 是保留名称 但如果我测试y它说 name 'y' not defined。 -
网络服务器有什么样的安全机制来运行python脚本?
-
@rodrigo:没错!在部署中,我希望它在自己的线程中运行,以将其与其他名称隔离。
-
@Joel:没有其他安全措施,这是一个用 web.py 编写的非常基础的项目(因此我想要一个简单的 Python 解决方案来安全地运行脚本)
-
啊,抱歉线程会超时。
标签: python security abstract-syntax-tree