Flask Jinja2开发中遇到的的服务端注入问题研究

Posted FreeBuf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask Jinja2开发中遇到的的服务端注入问题研究相关的知识,希望对你有一定的参考价值。

0×00. 前言 

作为一个安全工程师,我们有义务去了解漏洞产生的影响,这样才能更好地帮助我们去评估风险值。本篇文章我们将继续研究Flask/Jinja2 开发中遇到的SSTI (服务端模板注入)问题, 如果你从未听过SSTI 或者没有弄清楚它到底是个什么东东,建议您最好先阅读一下这篇文章<点击阅读原文查看链接>

0×01. 测试代码

为了更好地演示Flask/Jinja2 开发中的SSTI问题,我们搭建一个小的POC程序(基于Flask 框架),主要由两个python脚本组成:

Flask-test.py

Flask Jinja2开发中遇到的的服务端注入问题研究Flask Jinja2开发中遇到的的服务端注入问题研究

一些开发者可能认为为一个简单的404错误页面去单独创建一个模板文件是多余的,他们更喜欢在404 视图函数中用模板字符串(正如上述测试代码中的page_not_found函数中的template字符串)代替单独的404模板文件; 一些开发者还会在返回的错误页面中提示用户是哪一个URL导致了404错误,但他们不把错误的URL传递给render_template_string模板上下文,而是喜欢用%s动态地将问题URL传递给模板字符串,这些看起来都很OK。但实际上真的是这样的吗,让我们接着往下看

0×02. render_template_string 函数中默认上下文对象引起的SSTI问题

我们开始测试,404函数功能没得问题,确实显示了错误信息,并指出哪一个URL导致了此问题

Flask Jinja2开发中遇到的的服务端注入问题研究

到这里,很多人可能都想到了这个404函数存在的问题,对,就是XSS,是的,的确存在XSS漏洞,这也属于SSTI,但这篇文章不想讨论这一点, 如果你再深入思考一下,可能会发现这里存在代码注入,比如当我们的URL是下面这样,URL中包含了Jinjia2语法表达式:

http://10.1.100.3:5000/{{8+8}}

Flask Jinja2开发中遇到的的服务端注入问题研究

我们发现模板引擎执行了8+8,并返回了结果,这是一个简单的SSTI问题,我们再来看看其他有趣的SSTI 问题, 我们来看看

render_template_string 函数的定义:

def render_template_string(source, **context):"""Renders a template from the given template source string

with the given context.

:param source: the sourcecode of the template to be

rendered

:param context: the variables that should be available in the

context of the template.

"""ctx = _app_ctx_stack.top

ctx.app.update_template_context(context)return _render(ctx.app.jinja_env.from_string(source),

context, ctx.app)

这里有两个参数,一个是source,很简单就是需要渲染的模板字符串, 另一个是个包裹关键字传递参数(字典), 表示的是模板上下文,这里我们

就简单说一下这个Flask/Jinjia2开发中的模板上下文。主要有三个上下文,

一个是Jinjia globals<点击阅读原文查看链接> (http://jinja.pocoo.org/docs/dev/templates/#builtin-globals)

一个是Flask Template globals<点击阅读原文查看链接> (http://flask.pocoo.org/docs/0.10/templating/#standard-context)

最后一个是开发者自己显示添加的(这里暂且不表),前两个都是默认内置的(也就是上述代码中context参数默认值),这两个是我们要讨论的

render\_template\_string 默认上下文对象之request对象

经过一番调查,我们发现Flask Template globals 中有一个request对象,它表示当前请求对象(flask.request),它和你在视图代码中用到的

request对象(就是flask.request)一样,包含了所有的请求上下文信息,request 对象中包含一个environ对象,environ是一个字典,包含了所有的服务端环境变量信息,这个environ中有一个key:werkzeug.server.shutdown,这个key指向一个方法,这个方法是shutdown_server,就是用来关闭服务的,很显然这可以用来进行DOS攻击,

比如执行下面的URL,就可以关闭应用程序服务:<点击阅读原文查看链接>

http://10.1.100.3:5000/{{request.environ['werkzeug.server.shutdown']()}}

幸亏生产环境用的是gunicorn这样的WSGI 服务器而不是werkzeug,这样才不会造成更大影响

render\_template\_string 默认上下文对象之config对象

这config对象也是一个Flask template global,它代表中当前配置文件对象,也就是flask.config 中Config对象实例(源代码flask/config.py)

Flask Jinja2开发中遇到的的服务端注入问题研究

它是一个类似字典的对象,包含了应用程序所有的配置文件信息(你所有的用app.config.xxx | app.config['xxx'] 配置信息 都在config这个上下文对象中),在很多的例子中,这个condfig对象包含了很多敏感的信息,比如数据库连接信息,连接第三方服务的SECRET_KEY等

执行下面的URL,就可以获取当前应用程序所有的配置信息

<点击阅读原文查看链接>  

http://10.1.100.3:5000/{{config.items()}}

Flask Jinja2开发中遇到的的服务端注入问题研究

可以看到我们确实获取到了很多敏感的信息,包括数据库连接的密码, 所以不要认为把敏感信息保存在环境变量中就是安全的。

0×03. 反思render_template_string 默认上下文对象之config对象

0×02节已经提到过,render_template_string 默认上下文对象之config对象是flask.config中config对象的实例,它是一个类似字典的对象,config上下文对象有一些非常有意思的成员方法,比如:from_envvar , from_object ,from_pyfile , 当然还有一个成员属性root_path

这里我们先研究其成员方法from_object, 源代码如下:

Flask Jinja2开发中遇到的的服务端注入问题研究

这段代码意思就是,如果传入from_object方法的参数obj是str|unicode类型,那么就载入obj所代表的的模块,然后将参数obj所代表的模块中所有的大写属性加入到当前config对象实例中

我们来测试一下<点击阅读原文查看链接>

http://10.1.100.3:5000/{{config.from_object(‘os’)}}

这个url就是调用Flash Template Globals 中 config上下文对象中的from_object方法载入os模块,并将os模块中的大写属性加入config对象实例中

我们先来看一下os模块中有哪些大写属性值, 下面是一段测试代码,用来输出OS模块中所有的大写属性及其值

import os

for key in dir(os):

if key.isupper():

print key, ' ', getattr(os, key)

Flask Jinja2开发中遇到的的服务端注入问题研究

Flask Jinja2开发中遇到的的服务端注入问题研究

我们执行一下下面这个URL,看看是否真的导入了指定模块(这里指的是os一些大写属性,当然也包括一些os模块内置方法)中大写属性到当前上下文对象config中<点击阅读原文查看链接>http://10.1.100.3:5000/{{config.items()}}

恩,确实导入了OS模块中所有大写属性,其实这里给我们提供了一个思路,我们可以通过SSTI漏洞执行config上下文对象中from_object这类的方法导入一些模块,然后寻找可以callabled属性,以此来绕过Jinjia2模板沙盒。

0×04. 总结

本篇文章是我对Flask/Jinjia2 开发中遇到的一些问题的初步研究,config这个上下文对象其实还有一些其他的利用方式,危害也更大些, 我会在下篇文章中涉及

Origin Refer: https://nvisium.com/blog/2016/03/09/exploring-ssti-in-flask-jinja2/   <点击阅读原文查看链接>

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

以上是关于Flask Jinja2开发中遇到的的服务端注入问题研究的主要内容,如果未能解决你的问题,请参考以下文章

漏洞分析Flask框架(jinja2)&服务端模板注入漏洞(SSTI)

XCTF-攻防世界CTF平台-Web类——12Web_python_template_injection(SSTI服务器模板注入Flask框架之Jinja2模板渲染引擎)

Flask

Flask

flask

FLASK总结