2011-12-05 59 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 

這項工作與導入語句本身的複雜性無關。

注意:不要只打印&返回無,拋出有意義的異常,但你明白了!