我意识到这个问题已经被问过,但这种情况下略有不同。
我想运行(使用蟒蛇imageboard web.py ),这将允许用户提交的代码来生成新的图像。 该代码将是一个单个函数,它在x,像素的y坐标,并返回R,G,B值,例如以下形式:
def simpleGradient(xrel,yrel):
r = xrel*256
g = yrel*256
b = 0
return [r,g,b]
只有非常小的语法是必需的,它并不一定是蟒蛇。 使用exec
有限的范围似乎太不安全,并且使用PyPy或VM似乎过于复杂(我很新的这一切)。
而不是沙盒它,有没有一个更小的语言来执行代码Python的方式? 无论是蟒蛇(解析和白名单?),或数学的一个子集为导向,我可以嵌入语言?
这是我去解决。 对于这种方法的安全性的讨论,请参见
- 限制Python的语法来安全地执行用户代码。 这是一个安全的方法吗?
由于arifwn ,我进入探索Python的ast
(抽象语法树)模块。 该模块提供了一个类ast.NodeVisitor
遍历树。 此代码子类NodeVisitor
创建一个语法检查器,白名单必须在基本的数学代码。 函数调用和名字是专门监视,因为只有某些功能应该被允许和仅使用新的名称应该被允许。
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.passed=True
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
需要注意的是,这样的设计只接受代码的数学部分,提供了功能定义和返回语句。
白名单所有需要的安全构建体和特别白名单需要不安全的构造的这种方法,可被修饰以产生的Python许多有用的子集; 优秀的用户脚本!
请注意,为了让这个被安全地执行,它应该是在它自己的线程以超时,以减少名称冲突和超时。如果用户代码生成一个无限循环或相似。
有很多伟大的信息的pysandbox的PyPI页 。
文章来源: Executing mathematical user code on a python web server, what is the simplest secure way?