繁体   English   中英

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

[英]Executing mathematical user code on a python web server, what is the simplest secure way?

我知道以前曾问过这个问题,但是这种情况略有不同。

我想运行一个python图像板(使用web.py ),它将允许用户通过提交代码来生成新图像。 该代码将采用单个函数的形式,该函数采用像素的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似乎不必要地复杂(我对这一切还是很陌生的)。

除了将其沙盒化之外,还有没有一种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

请注意,这被设计为仅接受代码的数学部分,并提供了函数定义和return语句。

可以修改这种将所有必需的安全构造列入白名单,特别是将不安全的构造列入白名单的方法,以产生许多有用的Python子集。 非常适合用户脚本!

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

pysandbox pypi页面上有很多很好的信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM