打开页面,给出了代码,整理代码
import os
import flask
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
#显示源代码
@app.route('/shrine/')
#在shrine路径传入参数
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
#过滤()
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)
代码审计,目标是查看app.config[‘FLAG’] 。并对传入的参数进行了过滤。
查看了别的大佬写的题解,这里是SSTI模板类注入,之前没接触过。简单看了以下,没有特别深入,不过大概就是这样(没具体搞懂)
模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程
服务端把用户输入的内容渲染成模板就可能造成SSTI(Server-Side Template Injection)
模板渲染接受的参数需要用两个大括号括起来{{}},所以我们需要在大括号内
构造参数形成注入
首先看是否存在注入{{1+1}}
存在,那么我们需要构建payload来,查看app.config[‘FLAG’]。直接config是不行的,被黑名单了,我们需要通过别的函数来查看全局变量来获取当前的app因为我们的目标是app.config[‘FLAG’] 。如python的内置函数url_for或者get_flashed_messages,大佬给出的解释是,利用python对象之间的引用关系来调用被禁用的函数对象。
首先注入url_for.globals。
我们可以看到当前的app是current_app。继续注入当前app的config:
url_for.globals[‘current_app’].config
成功找到flag!