Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PythonWeb服务器上执行数学用户代码,最简单的安全方法是什么?_Python_Security_Web.py - Fatal编程技术网

在PythonWeb服务器上执行数学用户代码,最简单的安全方法是什么?

在PythonWeb服务器上执行数学用户代码,最简单的安全方法是什么?,python,security,web.py,Python,Security,Web.py,我意识到以前有人问过这个问题,但这个案例略有不同 我想运行一个PythonImageBoard(使用),它允许用户通过提交代码生成新图像。代码将采用单个函数的形式,该函数采用像素的x、y坐标并返回r、g、b值,例如: def simpleGradient(xrel,yrel): r = xrel*256 g = yrel*256 b = 0 return [r,g,b] 只需要非常小的语法,而且不一定是python。在有限的范围内使用exec似乎太不安全,而使用

我意识到以前有人问过这个问题,但这个案例略有不同

我想运行一个PythonImageBoard(使用),它允许用户通过提交代码生成新图像。代码将采用单个函数的形式,该函数采用像素的x、y坐标并返回r、g、b值,例如:

def simpleGradient(xrel,yrel):
    r = xrel*256
    g = yrel*256
    b = 0
    return [r,g,b]
只需要非常小的语法,而且不一定是python。在有限的范围内使用
exec
似乎太不安全,而使用PyPy或VM似乎不必要地复杂(我对这一切都很陌生)


是否有一种pythonic方式来用更小的语言执行代码,而不是将其沙箱化?要么是python的子集(解析和白名单?),要么是我可以嵌入的面向数学的语言?

有很多很棒的信息。

这就是我使用的解决方案。有关此方法安全性的讨论,请参阅

多亏了,我开始探索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子集;非常适合用户脚本


请注意,为了安全地执行此操作,它应该在自己的线程中超时,以减少名称冲突,并在用户代码生成无限循环或类似循环时超时。

我实际上会使用PyPy沙盒。我读到的其他几个答案都投了反对票。。。所以我还没有真正研究过PyPy——我会查一查,谢谢。一个伟大的问题,也许PyPy就是答案。我今天刚刚谈到,与lua相比,Python可能有点“短”。如果你有时间,我认为使用Python的内部编译器进行自己的编译会很有趣:哇。。。我正在考虑构建自己的语言(目前正在为uni任务编写PL0编译器),但这种方式可能会更有趣!这应该是一个独立的问题。对不起。我知道有人能帮我检查一下;如果他觉得没问题,我会把它改成更像一个答案。(否则我会删除它)。我的意思是:如果你把这个答案转换成一个新问题,你会有更多的目光(可能还有新的建议):)移动到