攻防世界Web_python_template_injection
题目:
就一句话啥也没有。python 模板注入。刚学菜鸡还不知道python模板有哪些注入漏洞,上网查一下。又学到一个知识点。
python常用的web 模板有 Django,Jinja2,Tornado, Flask等
其中,Flask模板中有两个渲染函数render_template和render_template_string。
render_template_string函数在渲染模板的时候使用了%s来动态的替换字符串,在渲染的时候会把**{undefined{}}**包裹的内容当做变量解析替换。
解题思路:
什么是模板注入呢?
为了写 html 代码的时候方便,很多网站都会使用模板,先写好一个 html 模板文件,
比如:
```python def test(): code = request.args.get('id') html = ''' <h3>%s</h3> '''%(code) return render_template_string(html) ```
这段代码中的 `html` 就是一个简单的模板文件,当开发者想要这个模板对应的样式时,可以直接用 `render_template_string` 方法来调用这个模板,从而直接把这个样
式渲染出来。而模板注入,就是指将一串指令代替变量传入模板中让它执行*,以这段代码为例,我们在传入 `code` 值时,可以用 `{{}}` 符号来包裹一系列代码,以此替代本应是
参数的 `id` :
http://..../?id={{代码}}
知道了什么是模板文件,接下来开始模板注入环节:
首先,先测试一下是不是确实能注入,构造一个简单的测试 url:
服务器回传`6` 的存在说明 `3+3` 这条指令被忠实地执行了。
接下来,开始想办法编代码拿到服务器的控制台权限:
首先,题目告诉我们这是一个 python 注入问题,那么脚本肯定也是 python 的。
思考怎样用 python 语句获取控制台权限:
想到了 `os.system` 和 `os.popen` 。前者返回 **退出状态码** , 后者 **以 file 形式** 返回 **输出内容**。
我们想要的是内容,所以选择 `os.popen` 。
知道了要用这一句,那么我要怎么找到这一句呢?
python 给我们提供了完整的寻找链([参考资料](https://www.cnblogs.com/tr1ple/p/9415641.html)):
__class__ :// 返回对象所属的类 __mro__ : // 返回一个类所继承的基类元组,方法在解析时按照元组的 顺序解析。 __base__ :// 返回该类所继承的基类 // __base__和__mro__都是用来寻找基类的 __subclasses__ // 每个新类都保留了子类的引用,这个方法返回一个类中仍然可引用的列表 __init__ : 类的初始化方法 __globals__ : 对包含函数全局变量的字典的引用
- 首先,找到当前变量所在的类:
服务器回复:告诉我们 这个变量的类是 'str' 了。
接下来,从这个类找到它的基类:
服务器回复:
<type 'str'>, <type 'basestring'>, <type 'object'>) 发现基类也有了。
- 然后,通过基类来找其中任意一个基类的引用列表:
这里有个小细节,`__mro__[]` 中括号里填谁其实区别都不大,这些基类引用的东西都一样。
从其中可以找到我们想要的 `os` 所在的 `site._Printer` 类,它在列表的第七十二位,
即 `__subclasses__()[71]` 。
- 通过 `__subclasses__()[71].__init__.__globals__['os'].popen('命令