题目
访问题目场景
这个界面很乱奥,我们访问网页源代码,我们就能看见我们需要审计的源码了
我们把python源码复制下来,进行分析
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
//匹配黑名单,将匹配到的config和self换成空字符
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)//主程序
看到这个源码我头都大了,我直接偷懒去看别的师傅写的WP,师傅们说这个是沙箱逃逸,python沙箱逃逸的方法是 利用python对象之间的引用关系来调用被禁用的函数对象
从
render_template_string
函数可以看出,这里应该是模板注入/shrine/{{1+1}}
从源码中可以看出,flag应该在config中,但是这里过滤了config无法使用
{{config}}
这里我们可以使用url_for
和get_flashed_messages
/shrine/{{url_for.__globals__}}
构造payloads: /shrine/{{url_for.__globals__['current_app'].config['FLAG']}}
python沙箱逃逸总结
让用户提交 Python 代码并在服务器上执行,是一些 OJ、量化网站重要的服务,很多 CTF 也有类似的题。为了不让恶意用户执行任意的 Python 代码,就需要确保 Python 运行在沙箱中。沙箱经常会禁用一些敏感的函数,例如 os,研究怎么逃逸、防护这类沙箱还是蛮有意思的。从整理好的代码中,我们得出 flag在config变量中,但config,self,(), 都被过滤了.假设没有过滤,可以尝试直接访问 config变量或者 {{self.dict}}来获取变量如果有过滤,就需要尝试通过全局变量实现沙盒逃逸