IMCAFS

Home

server-side template injection in the flask framework of server-side injection

Posted by millikan at 2020-03-17
all

Strict statement: This article is only for technical discussion and academic study, and is strictly prohibited to be used for other purposes (especially for illegal purposes, such as unauthorized attacks). Otherwise, it will bear the consequences on its own. It has nothing to do with the author and the platform. If there is anything wrong, please contact the author and the platform in time.

Preface

Flask is a lightweight MVC (also known as MTV, t: template) framework written in Python

See for details

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

For the flask framework itself, this article will not discuss it.

In this paper, we test several examples to show the security risks brought by the server template injection in the flask framework

0 × 01. Test 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. Security risks caused by string splicing or replacement in template string

Let's take a look at the Hello? SSTI function in the test code

Template content in function

template = '''<h2>Hello %s!</h2>''' % person['name'] http://localhost:5000/hello-template-injection?name=ForrestX386. {{person.secret}}

Secret value is leaked

Reason:

We know that jinja2 is used as the template rendering engine in flask, and {}} is used as the variable package identifier in jinja2. Jinja2 will parse and replace the {} package content as a variable during rendering. If the name = forrestx386. {{person. Secret}}} is passed in, then {}} will be replaced with the value of the secret element in the dictionary person during template rendering

**Raise local File Inclusion Vulnerability**

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

E: Content of \ haha.txt is leaked

Reason:

As above, when jinja2 renders the template, replace the contents of {get ﹣ user ﹣ file ('e: \ haha. TXT ')}}}} with the return value of get ﹣ user ﹣ file ('e: \ haha. TXT') function

How to solve the above problems:

Set template = "'< H2 > Hello% s! < / H2 >"'% person ['name ']

Change to template = '< H2 > Hello {{person ['name']}}! < / H2 > "'

In this way, jinja2 replaces the value of person ['name '] with {{person ['name']}}} during template rendering, instead of re rendering the content of person ['name '] (in this way, even if {}} is included in' person ['name '], it will not be rendered, but just as a normal string)

Security risks of 0 × 03. Render template string

We know that during template rendering (using jinja2 template engine), the flag render ﹐ template function will automatically transcode the template (common template suffixes, such as. HTML, . HTM, etc., the uncommon template suffix will not be automatically encoded with HTML, as will be described below) the content will be encoded with HTML entity to avoid XSS vulnerability, but the render ﹐ template ﹐ string function in flag will not automatically encode the template string to be rendered, which has XSS security risks

Here's an example

Trigger XSS

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

XSS pop-up does occur, indicating that the render template string function is not automatically HTML entity encoded

Note: if you are using Chrome browser during the test and there is no pop-up box, please turn off the chrome XSS filter

You can turn off the chrome XSS filter like this

Add ` - args – disable XSS auditor after the target`

OK, restart chrome, that's it

How to solve the above problems

We can add '| e' after the output content, which requires jinja2 template engine to encode the output content HTML entity and then output it to the user

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

Well, there's no XSS vulnerability

0 × 04. Security risks caused by using uncommon template suffix

Let's take a look at the hello_xssmethod in the test code, where the template is' template = 'hello. Unsafe'. The suffix unsafe is not the template suffix of automatic HTML coding supported by jinja2 template engine. If the content of the template is not written carefully or thoughtfully, XSS vulnerability can be caused. See the following example

If the content of hello.unsafe template is as follows:

{% 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>

Block good uses the autoescape method in jinja2, while block bad does not. Let's visit the following URL to see what happens

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

Yes, there is no XSS vulnerability in the block using the autoescape method (the autoescape function will automatically encode the wrapped block with HTML entity), while XSS vulnerability occurs in the block without the autoescape method (bad block), which indicates that render template will not automatically encode the template suffix that does not support automatic HTML entity encoding

So when using render template to render the template suffix that jinja2 template engine does not support automatic HTML entity encoding, please be careful and use the autoescape method where there is user input

How to solve the above problems

In addition to using the autoescape method, we can also add '| e' after the content to be rendered for HTML entity coding

For example, change the bad block content to

<h2>Bad</h2>

<p>

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

</p>

So there's no XSS vulnerability

 

0 × 05. Using HTML tag attribute field in template to bypass XSS filtering

In section 0 × 03, we talked about that render template string does not perform automatic HTML entity code conversion on the strings to be rendered, but you can use|e to perform HTML entity code conversion on the output content. Is it safe to use ` |e '? Not necessarily. Take a look at the following test:

Let's take a look at the Hello? Hi method in the test code

@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)

Although name uses|e to escape HTML entities, we can bypass it in the following ways

Browser access:

http://localhost:5000/html-attribute-xss?name=test onmouseover=document.title="xss-again" <a href={{ url_for('hello_xss')}}?name=test onmouseover=document.title="xss-again" >

Because the injected name parameter value appears in the attribute value of HTML tag after rendering, and|e will not filter the attribute value by HTML escape

How to solve:

Just use single or double quotes to enclose the value of the href

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

0 × 06. Summary

Through the above examples, we summarize some potential security risks and corresponding solutions brought by using templates in the re flash framework, and let us know some tips in using templates. In a word, when we use flask to develop, we must keep in mind that any input of the user is untrustworthy, and we should filter the input and output well

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

*Forrestx386, reprinted by freebuf.com