当前位置: 首页 > 面试题库 >

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

容柏
2023-03-14
问题内容

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

我想运行一个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子集。非常适合用户脚本!

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



 类似资料:
  • 最好的方法是什么?JCUDA是一个完美的映射到C CUDA还是完全不同?或者从Java调用C代码并共享结果是否有意义(链接列表是否可以访问)?

  • 问题内容: 我正在尝试运行从未知来源的C代码编译的程序。我想确保该程序无论如何都不会损害我的系统。例如,该程序可能在源代码中有类似东西,除非对代码进行彻底检查,否则无法检测到。 我想到了以下两种方法 在VMWare之类的VM中运行它 在Linux上构建Windows exe并在wine上运行 两者都不是很好的解决方案,我无法实现它们的自动化。并且在1的情况下可能会损坏VM。 任何帮助,将不胜感激。

  • 我有一些使用下面某个模块的网页抓取Python代码 硒 bs4 MySQLdb 调度器 在网上或云上运行代码的最简单方法或平台是什么?

  • 问题内容: 我想制作一个可以在本地运行其他人代码的Web服务…当然,我想将他们的代码访问权限限制在某些“沙盒”目录下,并且他们将无法连接到服务器的其他部分(数据库,主数据库网络服务器等) 最好的方法是什么? 运行VMware / Virtualbox: (+)我想它是一样安全的..即使有人设法“入侵” ..他们只入侵来宾计算机 (+)可以限制进程使用的CPU和内存 (+)易于设置..只需创建虚拟机

  • 本文向大家介绍在Ubuntu系统上安装Nginx服务器的简单方法,包括了在Ubuntu系统上安装Nginx服务器的简单方法的使用技巧和注意事项,需要的朋友参考一下 安装 Nginx      如果你安装了 Apache ,并且此时 Apache 在运行,那么请先修改一下配置文件(没有的同学直接跳过):      然后按以下两处修改(为了不和 Apache 冲突):              此时,

  • 问题内容: 我正在使用Node.js和Socket.io。我编写了一个应用程序,可以从服务器发送JavaScript代码段并在客户端上执行它们。JavaScript通过安全WebSocket(WSS)发送,并且客户端具有侦听器,该侦听器将执行通过服务器传递给它的任何代码。 这个简短的脚本演示了原理:http : //jsfiddle.net/KMURe/,您可以将onScript函数视为套接字侦听

  • 问题内容: 说我有一个类似的任务: 并行化每个compute()的最简单方法是什么(假设它们已经可以并行化了)? 我不需要严格匹配上面代码的答案,而只是一个常规答案。但是,如果您需要更多信息:我的任务是IO绑定的,这是针对Spring Web应用程序的,这些任务将在HTTP请求中执行。 问题答案: 我建议看一下ExecutorService。 特别是这样的事情: 请注意,如果列表很大,使用可能会很

  • 在回答这个问题之前,我必须说,我知道在客户端应用程序中硬编码密码是一种不好的做法,原因有很多。关于这个问题还有其他问题。这个问题的范围更窄,假设身份验证凭据必须驻留在客户端应用程序的代码上,原因是您无法控制的。 如果某些方法优于其他方法(例如:JPasswordField将密码存储在字符数组而不是字符串中),并且如果必须在Java应用程序中对其进行硬编码,您可以采取哪些措施使其更难获取? 更新: