emmmm。。。。之前在做SSTI的时候没做出来,现在根据wp复现一下,这题说实话过滤做的确实挺过分的,百度能搜到的常规思路都被ban掉了
.和[]‘"之类常用的东西都被ban的差不多了,测试下来唯一被留下来的一个过滤器逻辑和圆括号
关于过滤器,建议看这篇:
https://morblog.cc/posts/2946623354/
jinjia2环境很好判断,用到了里面的三个过滤器
attr(obj, name) 获取一个类的属性。
string(object) 转换为字符串输出
truncate(s, length=255, killwords=False, end=’…’, leeway=None)
返回被截断的字符串的复制。长度由第一个参数指定,默认为255。如果第二个参数为真,过滤器将最终删除文本。否则将丢弃最后一个单词。如果文本实际上被截断,它将附加一个省略号(“…”)。如果你想要一个不同于”…”的省略号您可以使用第三个参数指定它。仅超出第四个参数中给出的公差范围的字符串将不会被截断。
last(seq) 返回序列的最后一项,需要尽可能的对显式列表使用。
当时做的时候我搜到的wp都是用的list,但是用list有一个很麻烦的问题,emmmm。。。。,[]下标和’'""都被过滤了,当时我的思路就在这断了
看到wp的时候我惊了,直接拿string做截取,还是做的题少了
payload的基础结构:config|string()|truncate(75,True,app|string())|last,是的就是这个,截取下来的就是一个_
对照truncate的文档
killwords=True
app|string()是空,那么这个结构的把config转为字符串,然后用truncate截取出第75位的_,所有的字符都通过这个方式拼出来
查看当前类,如果没有过滤的话,应该是self.__class__
按照payload的格式拼接成:
{
{self|attr(config|string()|truncate(75,True,app|string())|last%2bconfig|string()|truncate(75,True,app|string())|last%2bconfig|string()|truncate(23,True,app|string())|last%2bconfig|string()|trunc