欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

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

来源:本站整理 作者:佚名 时间:2017-06-11 TAG: 我要投稿

作为一个安全工程师,我们有义务去了解漏洞产生的影响,这样才能更好地帮助我们去评估风险值。本篇文章我们将继续研究Flask/Jinja2 开发中遇到的SSTI (服务端模板注入)问题, 如果你从未听过SSTI 或者没有弄清楚它到底是个什么东东,建议您最好先阅读一下这篇文章
0×01. 测试代码
为了更好地演示Flask/Jinja2 开发中的SSTI问题,我们搭建一个小的POC程序(基于Flask 框架),主要由两个python脚本组成:
Flask-test.py
 #!/usr/bin/env python
# -*- coding:utf8 -*-
import hashlib
import logging
from datetime import timedelta
from flask import Flask
from flask import request
from flask import config
from flask import session
from flask import render_template_string
from Config import ProductionConfig
app = Flask(__name__)
handler = logging.StreamHandler()
logging_format = logging.Formatter(
'%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')
handler.setFormatter(logging_format)
app.logger.addHandler(handler)
app.config.secret_key = "\xe8\xf7\xb9\xae\xfb\x87\xea4
app.config.from_object(ProductionConfig) #将配置类中的配置导入程序
app.permanent_session_lifetime = timedelta(hours=6) #session cookies 有效期
page_size = 60
app.config['UPLOAD_DIR'] = '/var/www/html/upload'
app.config['PLUGIN_UPDATE_URL'] = 'https://ForrestX386.github.io/update'
app.config['PLUGIN_DOWNLOAD_ADDRESS'] = 'https://ForrestX386.github.io/download'
@app.route('/')
def hello_world():
return 'Hello World!'
@app.errorhandler(404)
def page_not_found(e):
template = '''
{%% block body %%}
Oops! That page doesn't exist.
%s
{%% endblock %%}
''' % (request.url)
return render_template_string(template), 404
if __name__ == '__main__':
app.run()
Config.py
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
class Config(object):
ACCOUNT = 'vpgame'
PASSWORD = 'win666666'
class DevlopmentConfig(Config):
pass
class TestingConfig(Config):
pass
class ProductionConfig(Config):
HOST = '127.0.0.1'
PORT = 65521
DBUSERNAME = 'vpgame'
DBPASSWORD = 'win666666'
DBNAME = 'vpgame'
一些开发者可能认为为一个简单的404错误页面去单独创建一个模板文件是多余的,他们更喜欢在404 视图函数中用模板字符串(正如上述测试代码中的page_not_found函数中的template字符串)代替单独的404模板文件; 一些开发者还会在返回的错误页面中提示用户是哪一个URL导致了404错误,但他们不把错误的URL传递给render_template_string模板上下文,而是喜欢用%s动态地将问题URL传递给模板字符串,这些看起来都很OK。但实际上真的是这样的吗,让我们接着往下看
0×02. render_template_string 函数中默认上下文对象引起的SSTI问题
我们开始测试,404函数功能没得问题,确实显示了错误信息,并指出哪一个URL导致了此问题

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

我们发现模板引擎执行了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),它和你在视图代码中用到的

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载