2011-12-05 48 views
1

我正在研究一个允许用户在我们的系统上运行其代码的系统。虽然他们的代码是沙盒,但我仍然想知道他们的代码是否使用某些语句,特别是导入。这用于快速检查恶意代码或代码是否违反平台的指导原则,它不会是唯一的检查,因为代码稍后也会被人类检查,但是自动筛选出最坏的情况会更可取。检查某些语句的Python代码

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

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

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

+0

人类需要做一个非常全面的检查。例如,通过使用'exec'命令,可以找到在此实现的任何简单系统的解决方法。 – Oliver

+0

我可能是错的,但我想不出除扫描源文件为文本文件之外的任何其他方法:如果您让python解释器执行它们,您将无法在导入语句和模块之前自行查询代码,级别的功能已经执行......但也许我缺少部分问题? – mac

+0

@Oliver ...仍然...即使人类可能会遇到麻烦,如果代码被模糊处理(例如酸洗/压缩/ rot13's等) – mac

回答

0

您可以使用ast python模块来分析Python代码。见我的回答非常类似的问题在这里:

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

这里是你的import语句问题的解决方案:

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

当然,这不会的情况下帮助恶意用户是花费了大量精力来模糊他的代码,但是,唯一的办法就是使用真正的沙箱。但这首先不是你的问题。

+0

坦率地说,我不明白这应该比使用正则表达式更好......它最多只会慢一个数量级,而且仍然具有相同的局限性......或者我错过了什么? – mac

+0

您也可以使用此方法解决奖励问题,这将很难使用正则表达式。 – hochl

+0

也不能用简单的技巧,比如Liquid Fire的代码。 – Voo

3

我真的不费劲去尝试,因为

1024 ** 1024 ** 1024 

仍然会咀嚼你的解释做这种人造沙盒。

甚至这个

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

如果你想一些安全直视pypy的sandbox其即将运行不受信任的Python代码最安全的方式。有几个Python模块,如pysandbox,但我个人建议pypy沙箱。

+0

我猜测OP不希望这样做的安全,鉴于他已经使用沙箱。这种检查*可能*旨在识别打破沙箱的企图,并强制禁止...... – mac

1

你不能仅仅通过代码的静态分析做到这一点,因为它总是可以做技巧性的东西,如:

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

正如你所看到的,在看反汇编,代码或AST韩元”没有任何地方甚至包含字符串“导入”:

>>> 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 
+0

我认为chr(73)是一个错误,因为这是ascii为我和“导入”为我抛出错误。对于小写字母i,105可以正常工作。 – Voo

+0

的确如此,谢谢。 –

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

你所要做的是一个常见的场景:你是通过在沙箱中运行已经在做的代码动态分析。在你最喜欢的静态分析,以及使用另一个工具读取程序给你。

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

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

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

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

例如,如果您只是想查看正在使用的模块种类,则可以使用imports checker。为了处理更复杂的场景,您可以自定义和扩展功能。看看他们的documentation for enhancing PyLint

看看在tutorial上手:

1

虽然真正的沙拳击确实是非常困难的,如果它是进口声明你试图抓住,这样考虑:

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

这项工作与导入语句本身的复杂性无关。

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