【攻防世界】shrine

题目考点

模板注入

Writeup

进入题目,发现一串python代码

 稍加整理,可以发现这是python中的flask框架,有可能存在ssti漏洞模块注入,代码中两次提到了路径"/"与路径"/shrine",对于这两个路径尝试进行SSTI注入

import flask
import os 
app = flask.Flask(__name__) #创立实例
app.config['FLAG'] = os.environ.pop('FLAG') #以键值对的方式,保存app的信息
@app.route('/') #@表示装饰器,本质是扩展原本函数功能的一种函数,app.route('URL')在程序运行时,装饰一个视图函数,用给定的URL规则和选项注册它
def index(): 
    return open(__file__).read() #打开文件读取
@app.route('/shrine/') #在程序运行时注册一个/sharine/的路经
def shrine(shrine):
 
    def safe_jinja(s): 
        s = s.replace('(', '').replace(')', '') #替换(与为空,替换)为空
        blacklist = ['config', 'self']   #黑名单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) 

在shrine路径下测试ssti能正常执行

接着分析源码,第一段注册了一个名为FLAG的config,猜测这就是flag,如果没有过滤可以直接{{config}}即可查看所有app.config内容,但是这题设了黑名单[‘config’,‘self’] 并且在第二段过滤了括号

app.config['FLAG'] = os.environ.pop('FLAG')
s = s.replace('(', '').replace(')', '') 
blacklist = ['config', 'self']

然后下面的代码将黑名单中的值遍历,并替代为空

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

这样使本来可以直接出答案的payload——/shrine/{{config}}——变成了空

不过python还有一些内置函数,比如url_for和get_flashed_messages

/shrine/{{url_for.__globals__}}

 

 看到current_app意思应该是当前app,那我们就当前app下的config:

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

拿到flag

 

posted @ 2025-04-28 21:02  Antoniiiia  阅读(117)  评论(1)    收藏  举报