服务端注入之Flask框架中服务端模板注入问题

栏目: 编程工具 · 发布时间: 7年前

内容简介:服务端注入之Flask框架中服务端模板注入问题

0×00. 前言

Flask 是 python 语言编写的轻量级的MVC (也可以称为MTV, T: Template)框架

具体详见

http://docs.jinkan.org/docs/flask/

对于Flask 框架本身,本文不做讨论。

本文主要通过几个例子,测试说明下Flask框架中服务端模板注入带来的安全隐患

0×01. 测试Code

from flask import Flask, request, render_template_string, render_template
app = Flask(__name__)
@app.route('/hello-template-injection')
def hello_ssti():
person = {'name': "world", 'secret': "UGhldmJoZj8gYWl2ZnZoei5wYnovcG5lcnJlZg=="}
if request.args.get('name'):
person['name'] = request.args.get('name')
template = '''<h2>Hello %s!</h2>''' % person['name']
return render_template_string(template, person=person)
@app.route('/hello-xss')
def hello_xss():
name = "world"
template = 'hello.unsafe'# 'unsafe' file extension... totally legit.
if request.args.get('name'):
name = request.args.get('name')
return render_template(template, name=name)
@app.route('/html-attribute-xss')
def hello_hi():
template = '''<title>No Injection Allowed!</title>
<a href={{ url_for('hello_xss')}}?name={{ name |e}}>
Click here for a welcome message</a>'''
name = "world"
if request.args.get('name'):
name = request.args.get('name')
return render_template_string(template, name=name)
####
# Private function if the user has local files.
###
def get_user_file(f_name):
with open(f_name) as f:
return f.readlines()
app.jinja_env.globals['get_user_file'] = get_user_file# Allows for use in Jinja2 templates
if __name__ == "__main__":
app.run(debug=True)

0×02. 模板字符串中字符串拼接或替换引发的安全隐患

我们看一下测试代码中的 hello_ssti函数

函数中模板内容

template = '''<h2>Hello %s!</h2>''' % person['name']

就是简单的字符串替换,这会引发什么安全问题吗?

我们看例子:

运行后,浏览器访问: http://localhost:5000 (Flask开发的程序,默认监听端口为5000)

服务端注入之Flask框架中服务端模板注入问题

OK, 打印Hello World。

但是,如果传入的name 参数值为恶意代码会怎么样?

引发敏感信息泄露

http://localhost:5000/hello-template-injection?name=ForrestX386. {{person.secret}}

服务端注入之Flask框架中服务端模板注入问题

secret 值被泄露

原因:

我们知道Flask 中使用了Jinja2 作为模板渲染引擎,{{}}在Jinja2中作为变量包裹标识符,Jinja2在渲染的时候会把{{}}包裹的内容当做变量解析替换,如果传入的name=ForrestX386. {{person.secret}},那么在模板渲染的时候就会将{{}}替换成字典person中secret元素的值

**引发本地文件包含漏洞**

http://localhost:5000/hello-template-injection?name=ForrestX386. {{get_user_file('E:\haha.txt')}}

服务端注入之Flask框架中服务端模板注入问题

E:\haha.txt 内容被泄露

原因:

同上,Jinja2在渲染模板的时候,将{{get_user_file(‘E:\haha.txt’)}}的内容替换成get_user_file(‘E:\haha.txt’)函数的返回值

如何解决上述问题:

将template = ”’<h2>Hello %s!</h2>”’ % person['name']

更改为template = ”’<h2>Hello {{person['name']}}!</h2>”’

这样以来,Jinja2在模板渲染的时候将person['name']的值替换掉{{person['name']}}, 而不会对person['name']内容进行二次渲染(这样即使`person['name']中含有{{}}也不会进行渲染,而只是把它当做普通字符串)

0×03. render_template_string 的安全隐

我们知道Flask render_template函数在模板渲染(使用Jinja2模板引擎)的时候,会自动对模板(常见的模板后缀才进行自动HTML转码,比如.html,.htm等,不常见的模板后缀是不会进行HTML自动编码的,下面会介绍到)内容进行HTML实体编码,从而避免XSS漏洞的发生,但是Flask中的render_template_string 函数却不会对要渲染的模板字符串进行自动HTML实体编码,存在XSS安全隐患

下面看一个例子

引发XSS

http://localhost:5000/hello-template-injection?name=ForrestX386. <script>alert(“welcome to visit ForrestX386.github.io.”)</script>

服务端注入之Flask框架中服务端模板注入问题

确实发生了XSS弹窗,说明render_template_string 函数没有进行自动HTML实体编码

注: 如果你在测试过程中使用的是chrome浏览器,且没有弹框,请把chrome XSS 过滤器给关闭

你可以这样关闭chrome xss 过滤器

在目标后面加上 `–args –disable-xss-auditor `

服务端注入之Flask框架中服务端模板注入问题

确定,重启chrome,就可以了

如何解决上述问题

我们可以在输出的内容后面加上 `| e` ,这样就要求Jinja2模板引擎 将输出内容HTML实体编码后再输出给用户

template = '<h2>Hello {{ person['name'] | e }}!</h2>'

恩,这样就不会有XSS 漏洞了

服务端注入之Flask框架中服务端模板注入问题

0×04. 使用不常见的模板后缀引发的安全隐患

我们看一下测试代码中的hello_xss 方法,其中模板为 `template = ‘hello.unsafe’` , 后缀unsafe 不是Jinja2模板引擎支持的自动HTML编码的模板后缀,如果编写模板内容的时候不够细心或者考虑不周全,则可能引发XSS漏洞。 看下面的例子

如果hello.unsafe模板内容是这样的:

{% autoescape true %}
<h2>Good</h2>
<p>
Hello {{ name }}! I don't trust your input. I escaped it, just in case.
</p>
{% endautoescape %}
<h2>Bad</h2>
<p>
I trust all data! How are you {{ name }}?
</p>

区块Good 使用Jinja2中autoescape方法,而区块Bad 没有使用,我们访问下面的url看看会发生什么

http://localhost:5000/hello-xss?name=ForrestX386.<script>document.title="xss";</script>

服务端注入之Flask框架中服务端模板注入问题

是的,使用autoescape方法的区块没有XSS漏洞(autoescape函数会自动将所包裹区块自动HTML实体编码),而没有使用autoescape方法的区块(Bad区块)发生XSS漏洞,说明render_template是不会对不支持自动HTML实体编码的模板后缀进行自动HTML实体编码

所以当使用render_template渲染Jinja2模板引擎不支持自动HTML实体编码的模板后缀的时候,请小心仔细一些,在有用户输入的的地方使用autoescape方法

如何解决上述问题

除了使用autoescape方法,我们还可以在要渲染的内容后面加上 ` |e ` 进行HTML实体编码

比如将Bad 区块内容更改为

<h2>Bad</h2>

<p>

I trust all data! How are you {{ name |e }}?

</p>

这样就不会有XSS漏洞了

服务端注入之Flask框架中服务端模板注入问题

0×05. 利用模板中html标签属性字段绕过xss过滤

我们在0×03节谈到了render_template_string 不会对要渲染的字符串进行自动HTML实体编码转换,但是可以使用|e 对输出内容进行HTM实体编码转换,那么使用 `|e` 一定安全吗? 那倒不一定,不信看看下面的测试:

我们看一下测试代码中的hello_hi方法

@app.route('/html-attribute-xss')
def hello_hi():
template = '''<title>No Injection Allowed!</title>
<a href={{ url_for('hello_xss')}}?name={{ name |e}}>
Click here for a welcome message</a>'''
name = "world"
if request.args.get('name'):
name = request.args.get('name')
return render_template_string(template, name=name)

name 虽然使用|e 进行html实体转义 ,但我们可以通过下面的方式进行绕过

浏览器访问:

http://localhost:5000/html-attribute-xss?name=test onmouseover=document.title="xss-again"

打开的界面是这样的:

服务端注入之Flask框架中服务端模板注入问题

当我们把鼠标放在超链接上的时候

服务端注入之Flask框架中服务端模板注入问题

注意到没有 title 变成了xss-again,说明xss注入成功

原因:

name 参数传入的值为test onmouseover=document.title=”xss-again”,替换之后变成

<a href={{ url_for('hello_xss')}}?name=test onmouseover=document.title="xss-again" >

因为注入的name参数值渲染后出现在了HTML标签的属性值中,而|e 是不会对属性值进行HTML转义过滤的

如何解决:

只要使用单引号或者双引号将href的值括起来就可以了

<a href="{{ url_for('hello_xss')}}?name={{ name |e}}">

0×06. 总结

通过上面的例子,我们总结了再Flask框架中使用模板可能带来的一些安全隐患以及对应的解决方法,让我们了解了使用模板中一些tips。总之,我们在使用Flask开发的时候,一定要谨记:用户的任何输入都是不可信的,要在输入和输出端都做好过滤

Origin Refer: https://nvisium.com/blog/2015/12/07/injecting-flask/

*本文作者ForrestX386,转载请注明来自FreeBuf.COM


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Collective Intelligence

Programming Collective Intelligence

Toby Segaran / O'Reilly Media / 2007-8-26 / USD 39.99

Want to tap the power behind search rankings, product recommendations, social bookmarking, and online matchmaking? This fascinating book demonstrates how you can build Web 2.0 applications to mine the......一起来看看 《Programming Collective Intelligence》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具