限制 Python 的语法以安全地执行用户代码.这是一种安全的方法吗? [英] Restricting Python's syntax to execute user code safely. Is this a safe approach?

查看:25
本文介绍了限制 Python 的语法以安全地执行用户代码.这是一种安全的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原始问题:

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

  • 我希望能够在 python 网络服务器上运行用户提交的代码.代码在本质上将是简单和数学的.

由于需要这么小的 Python 子集,我目前的方法是通过遍历 Python 的抽象语法树来将允许的语法列入白名单.函数和名称得到特殊处理;仅允许明确列入白名单的函数,并且仅允许未使用的名称.

As such a small subset of Python is required, my current approach is to whitelist allowable syntax by traversing Python's abstract syntax tree. Functions and names get special treatment; only explicitly whitelisted functions are allowed, and only unused names.

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

这似乎接受了所需的语法,但我对编程还是相当陌生,可能会遗漏许多巨大的安全漏洞.

This seems to accept the required syntax, but I am reasonably new to programming and could be missing any number of gaping security holes.

所以我的问题是:这是否安全,是否有更好的方法,我是否应该采取任何其他预防措施?

So my questions are: Is this secure, is there a better approach, and are there any other precautions I should be taking?

推荐答案

有两点我注意到你仍然可以改进:

Two points I noticed that you could still improve:

您应该始终转义可以从某种形式的用户输入生成的任何输出.在您的示例中,不允许的标识符将未经修改地镜像回输出.这可能会被利用,一个例子是跨站点脚本.因此,我会另外转义任何此类错误消息以防止出现这种情况.

You should always escape any output that can be generated from some form of user input. In your example, the unallowed identifiers get mirrored unmodified back to the output. This could potentially be exploited, one example being Cross Site Scripting. Therefore I would additionally escape any such error message to prevent this.

您需要注意的另一件事是拒绝服务攻击.想象一下,有人创建了一个 Ackermann 函数和一个脚本,将它提交给您的服务器数千次……为了防止这种情况发生,您应该对提交的任何代码的执行时间进行时间限制.这是必不可少的,因为这种类型的攻击"通常是无意发生的 - 有人设法产生了无限循环.

Another thing you need to be aware of is Denial-of-Service attacks. Imagine someone whips up an Ackermann function and a script to submit it a couple of thousand times to your server... To prevent this, you should timebox the execution time of any code being submitted. This is essential, because this type of "attack" often happens unintentionally - someone managed to produce an infinite loop.

最后,我还建议您更新您的 Python 版本以防止 "hashDoS" 攻击.

Finally, I would also recommend to update your Python version to prevent a "hashDoS" attack.

这篇关于限制 Python 的语法以安全地执行用户代码.这是一种安全的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆