检查Python代码中的某些语句

检查Python代码中的某些语句,python,Python,我正在开发一个允许用户在我们的系统上运行代码的系统。虽然他们的代码是沙盒式的,但我仍然想知道他们的代码是否使用了某些语句,尤其是导入语句。这用于对恶意代码或违反平台指南的代码进行快速检查,这不是唯一的检查,因为代码稍后也会由人检查,但最好自动过滤掉最坏的情况 那么,在不执行代码的情况下,检查他们的代码(例如)是否导入sys或sys的一部分的最佳方法是什么?我希望有一种比正则表达式搜索代码更好的方法 附加问题:更复杂的语句呢?例如,从模块栏调用foo 编辑:这不是关于安全性的问题。它是关于在代码中

我正在开发一个允许用户在我们的系统上运行代码的系统。虽然他们的代码是沙盒式的,但我仍然想知道他们的代码是否使用了某些语句,尤其是导入语句。这用于对恶意代码或违反平台指南的代码进行快速检查,这不是唯一的检查,因为代码稍后也会由人检查,但最好自动过滤掉最坏的情况

那么,在不执行代码的情况下,检查他们的代码(例如)是否导入sys或sys的一部分的最佳方法是什么?我希望有一种比正则表达式搜索代码更好的方法

附加问题:更复杂的语句呢?例如,从模块栏调用foo

编辑:这不是关于安全性的问题。它是关于在代码中查找某些语句的。见我的评论。此用户代码将只在用户沙箱中运行,因此他们可以破坏自己的沙箱。但如果他们的代码得到“认证”,它可以在其他用户的沙盒中运行,在得到认证之前需要进行检查。如果自动检查能够发现最严重的违规行为,那将非常有用。

您可以使用ast python模块来分析python代码。请参见我对一个非常类似问题的回答:

以下是您的导入语句问题的解决方案:

import ast
import sys

class FunctionNameFinder(ast.NodeVisitor):
        def visit_Import(self, node):
                print "Importing on line", node.lineno, ":",
                for i in node.names: print i.name,
                print

with open(sys.argv[1], 'rU') as f:
        FunctionNameFinder().visit(ast.parse("".join(f.readlines())))
当然,在恶意用户花费大量精力混淆其代码的情况下,这不会有帮助,但是,唯一的办法是使用真正的沙箱。但这并不是您首先要问的问题。

您可以使用ast python模块来分析python代码。请参见我对一个非常类似问题的回答:

以下是您的导入语句问题的解决方案:

import ast
import sys

class FunctionNameFinder(ast.NodeVisitor):
        def visit_Import(self, node):
                print "Importing on line", node.lineno, ":",
                for i in node.names: print i.name,
                print

with open(sys.argv[1], 'rU') as f:
        FunctionNameFinder().visit(ast.parse("".join(f.readlines())))

当然,在恶意用户花费大量精力混淆其代码的情况下,这不会有帮助,但是,唯一的办法是使用真正的沙箱。但这并不是你首先要问的问题。

我真的不会费心去做这种人工沙箱,因为

1024 ** 1024 ** 1024
你的翻译还是会吃力的

甚至这个

eval("__vzcbeg__('gvzr').nfpgvzr()")

如果您想要一些安全性,请查看pypy的its,它是运行不受信任的python代码的最安全的方法。有一些只支持python的模块,比如,但我个人建议使用pypy沙盒。

我真的不想尝试这种人工沙盒,因为

1024 ** 1024 ** 1024
你的翻译还是会吃力的

甚至这个

eval("__vzcbeg__('gvzr').nfpgvzr()")

如果您想要一些安全性,请查看pypy的its,它是运行不受信任的python代码的最安全的方法。有一些只使用python的模块,如,但我个人建议使用pypy沙盒。

您不能仅通过静态分析代码来实现这一点,因为它总是会做一些棘手的事情,例如:

>>> getattr(__builtins__, "__" + chr(105) + "mport__")("sys")
<module 'sys' (built-in)>

您不能仅仅通过静态分析代码来实现这一点,因为它总是会做一些棘手的事情,例如:

>>> getattr(__builtins__, "__" + chr(105) + "mport__")("sys")
<module 'sys' (built-in)>

我认为你根本无法可靠地检测到那种东西。考虑以下事项:

>>> f = None
>>> b = vars()[[f for f in vars() if 'ti' in f][0]]
>>> m = getattr(b, [f for f in dir(b) if 't_' in f][0])
>>> m('x\x9c+\xae,\x06\x00\x02\xc1\x01`'.decode('zip'))
<module 'sys' (built-in)>

我认为你根本无法可靠地检测到那种东西。考虑以下事项:

>>> f = None
>>> b = vars()[[f for f in vars() if 'ti' in f][0]]
>>> m = getattr(b, [f for f in dir(b) if 't_' in f][0])
>>> m('x\x9c+\xae,\x06\x00\x02\xc1\x01`'.decode('zip'))
<module 'sys' (built-in)>

您试图做的是一个常见的场景:您已经在沙箱中运行代码进行动态分析。除此之外,您还希望使用其他工具进行静态分析,并为您阅读程序

这两种方法都有各自的缺点,由于计算的性质,它们都不能保证为您提供各种可能出错的场景;然而,两者的结合仍然以更高的置信度为您提供了许多有用的信息

在其他流行语言中,例如C/C++,有一些健壮的工具,例如Lint,可以深入分析代码并报告许多潜在问题,包括与安全相关的问题

不幸的是,Python没有具有那么高健壮性级别的工具。尽管如此,你仍然可以做很多事情。我认为你最好的选择是使用派林

PyLint提供了一些用于代码分析的标准规则,但是您可以覆盖这些规则来定制自己的代码

例如,如果您只是想查看正在使用的模块类型,那么可以使用。为了处理更复杂的场景,您可以自定义和扩展功能。看看他们的照片


请看一下入门指南:

您尝试做的是一个常见的场景:您已经在沙箱中运行了代码的动态分析。除此之外,您还希望使用其他工具进行静态分析,并为您阅读程序

这两种方法都有各自的缺点,由于计算的性质,它们都不能保证为您提供各种可能出错的场景;然而,两者的结合仍然以更高的置信度为您提供了许多有用的信息

在其他流行语言中,例如C/C++,有一些健壮的工具,例如Lint,可以分析 深入研究代码并报告许多潜在问题,包括与安全相关的问题

不幸的是,Python没有具有那么高健壮性级别的工具。尽管如此,你仍然可以做很多事情。我认为你最好的选择是使用派林

PyLint提供了一些用于代码分析的标准规则,但是您可以覆盖这些规则来定制自己的代码

例如,如果您只是想查看正在使用的模块类型,那么可以使用。为了处理更复杂的场景,您可以自定义和扩展功能。看看他们的照片


看一下开始:

P>而真正的沙拳确实很难,如果是你试图抓住的进口语句,考虑一下:

>>> org_imp = __builtins__.__import__
>>> def imp_hook(*args, **kw):
    if args[0] == 'sys':
        print 'Gotcha!!'
        return None
    return org_imp

>>> __builtins__.__import__ = imp_hook
>>> import sys
Gotcha!!
>>> sys
>>> print sys
None
这项工作与import语句本身的复杂性无关


注意:不要只打印并返回None,抛出有意义的异常,但是你知道了
>>> org_imp = __builtins__.__import__
>>> def imp_hook(*args, **kw):
    if args[0] == 'sys':
        print 'Gotcha!!'
        return None
    return org_imp

>>> __builtins__.__import__ = imp_hook
>>> import sys
Gotcha!!
>>> sys
>>> print sys
None
这项工作与import语句本身的复杂性无关



注意:不要只打印并返回None,抛出有意义的异常,但是你知道了

人类需要做一个非常全面的检查。可以找到一种方法绕过您在这里实现的任何简单系统,例如,通过使用exec命令。我可能错了,但除了将源文件扫描为文本文件外,我想不出任何其他方法:如果让python解释器执行它们,在执行导入语句和模块级函数之前,您将无法自省地查询代码。。。但也许我遗漏了问题的一部分?@Oliver…但仍然。。。如果代码被混淆(例如pickle/zipped/rot13等),甚至人类也可能会遇到麻烦。安全性由沙箱完成。但该系统将允许人们在检查后在其他人的沙箱中运行他们的代码。因此,如果他们的代码被混淆,它将立即被拒绝。如果没有混淆,将检查一些限制,如sys、os.system、subprocess。理想情况下,它会告诉我那些冒犯性的陈述是哪一行,这样我就可以手动检查它们。人类需要做一个非常全面的检查。可以找到一种方法绕过您在这里实现的任何简单系统,例如,通过使用exec命令。我可能错了,但除了将源文件扫描为文本文件外,我想不出任何其他方法:如果让python解释器执行它们,在执行导入语句和模块级函数之前,您将无法自省地查询代码。。。但也许我遗漏了问题的一部分?@Oliver…但仍然。。。如果代码被混淆(例如pickle/zipped/rot13等),甚至人类也可能会遇到麻烦。安全性由沙箱完成。但该系统将允许人们在检查后在其他人的沙箱中运行他们的代码。因此,如果他们的代码被混淆,它将立即被拒绝。如果没有混淆,将检查一些限制,如sys、os.system、subprocess。理想情况下,它只会告诉我这些违规语句是哪一行,这样我就可以手动检查它们了。坦率地说,我不认为这比使用正则表达式更好。。。它最多会慢一个数量级,并且仍然有相同的限制。。。。或者我遗漏了什么?你也可以用这个方法来解决奖金问题,这将很难使用正则表达式。同样,上面的Liquid Fire代码这样的简单技巧也不起作用。嗯。。。我不认为从foo导入栏进行匹配是一项很难用正则表达式实现的任务六羟甲基三聚氰胺六甲醚。。。尽管如此,我仍然认为使用ast库更好,但真正的解决方案肯定需要一个沙箱:坦白说,我不认为这比使用正则表达式更好。。。它最多会慢一个数量级,并且仍然有相同的限制。。。。或者我遗漏了什么?你也可以用这个方法来解决奖金问题,这将很难使用正则表达式。同样,上面的Liquid Fire代码这样的简单技巧也不起作用。嗯。。。我不认为从foo导入栏进行匹配是一项很难用正则表达式实现的任务六羟甲基三聚氰胺六甲醚。。。尽管如此,我还是认为使用ast库更好,但真正的解决方案肯定涉及到沙箱:我猜OP不希望这样做是为了安全,因为他已经使用了沙箱。这种检查可能是为了识别破坏沙箱的企图,并强制执行禁令……我猜OP不希望这样做是为了安全,因为他已经在使用沙箱了。这种检查可能是为了识别试图破坏沙箱的行为,并强制执行禁令……我认为chr73是一个错误,因为这是我的ascii,导入会为我抛出错误。虽然小写i为105,但工作正常。我认为chr73是一个错误,因为这是as cii for I和Import为我抛出错误。虽然小写i为105,但效果良好。