检查Python代码中的某些语句

时间:2011-12-05 13:26:02

标签: python

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

那么在不执行代码的情况下,最好的方法是检查他们的代码是否导入sys(或sys的一部分)?我希望有一个更好/更好的方式然后正则表达式搜索该代码。

奖金问题:更复杂的陈述怎么样?例如,从模块foo调用bar

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

6 个答案:

答案 0 :(得分:3)

我真的不愿意尝试做这种人工沙盒,因为

1024 ** 1024 ** 1024

仍然会咀嚼你的翻译。

甚至是

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

如果你想要一些安全性,请查看pypy的sandbox,了解运行不受信任的python代码的最安全方法。有一些只有python的模块,如pysandbox,但我个人建议使用pypy沙箱。

答案 1 :(得分:1)

你不能仅仅通过对代码的静态分析来做到这一点,因为它总是可以做一些棘手的事情,例如:

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

正如您所看到的,查看反汇编,代码或ast不会有帮助,因为它甚至包含字符串&#34; import&#34;:

>>> import dis
>>> dis.dis(lambda: getattr(__builtins__, "__" + chr(105) + "mport__")("sys"))
  1           0 LOAD_GLOBAL              0 (getattr)
              3 LOAD_GLOBAL              1 (__builtins__)
              6 LOAD_CONST               1 ('__')
              9 LOAD_GLOBAL              2 (chr)
             12 LOAD_CONST               2 (105)
             15 CALL_FUNCTION            1
             18 BINARY_ADD
             19 LOAD_CONST               3 ('mport__')
             22 BINARY_ADD
             23 CALL_FUNCTION            2
             26 LOAD_CONST               4 ('sys')
             29 CALL_FUNCTION            1
             32 RETURN_VALUE

答案 2 :(得分:1)

我认为你根本无法可靠地发现那种东西。请考虑以下事项:

>>> 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)>

答案 3 :(得分:1)

虽然真正的沙子拳击确实非常困难,但是如果它是你试图抓住的 import 声明,请考虑一下:

>>> 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语句本身的复杂程度如何,这项工作都是如此。

注意:不要只打印&amp;返回无,抛出有意义的异常,但你明白了!

答案 4 :(得分:0)

您可以使用ast python模块来分析Python代码。请参阅我在这里回答一个非常相似的问题:

https://stackoverflow.com/a/8255293/589206

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

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())))

当然,如果恶意用户花费大量精力来模糊他的代码,这将无济于事,但是,唯一的方法就是使用真正的沙箱。但这首先不是你的问题。

答案 5 :(得分:0)

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

这两种方法都有其自身的缺点,并且由于计算的性质,它们都不能保证为您提供各种潜在的方案出错;但是,两者的结合仍然可以在更高的置信度下为您提供大量有用的信息。

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

不幸的是,Python没有具有高稳健性水平的工具。话虽如此,你仍然可以做很多事情。我认为你最好的选择就是使用PyLint。

PyLint附带了一些代码分析的标准规则,但您可以覆盖这些规则以自定义您自己的代码气味。

例如,如果您只是希望看到正在使用的模块类型,则可以使用imports checker。要处理更复杂的方案,您可以自定义和扩展功能。看看他们的documentation for enhancing PyLint

看一下tutorial开始: