Flask is a Python web application micro-framework. The term micro means that a developer doesn’t have to install any additional libraries or tools and there is no database abstraction layer. The framework is stand-alone and designed for rapid development.
There is no form validation and other elements, but the community has been contributing to this micro framework to build robust Flask extensions to solve different problems. The community support for this framework is one of the great things about it.
In such a micro framework, security should be taken into consideration as there are multiple vulnerabilities by default. In this article, we will discuss some flask security best practices to ensure your application runs smoothly.
Jinja2 Templating and User-Input
A simple form asking user input to post some status:
A jinja2 template which renders other users’ status:
Our endpoint which handles this request:
The status posted by the user will be used as p class attribute inside the tag, and also as an href attribute.
There are some bullet points to remember while developing an app in Flask.
- Do not generate an HTML template without Jinja2.
- Data should never be sent from uploaded files.
- Attribute values should always be quoted.
If you want to read more on this topic you can refer to OWASP.
Cross-Site Request Forgery or CSRF is an attack that uses the victim’s credentials to perform undesired actions on behalf of the victim. This vulnerability can become more severe if chained with XSS or Mis-Configured CORS, etc.
By default, the flask framework has no CSRF protection but we can use Flask-WTF extension to enable the CSRF protection. Below is an example of how CSRF protection can be enabled.
This will enable CSRF protection globally in the app and we will be protected against CSRF. Each form will have a hidden input field containing our CSRF protection token generated randomly by the Flask-WTF. We will have to use it in our forms.
We have to keep some bullet points in mind while making the routes to keep our app protected from CSRF attacks.
- GET requests should be used to retrieve data from the web.
- Sensitive routes that change information should be performed with POST requests in the proper form submission.
- Requests that change the state should be mandated with a CSRF token generated by the server and sent to the user’s browser.
- The Origin and Referer header must be validated.
In the flask framework, directory traversal can happen if an attacker uploads a file with the name ../../../etc/passwd. If an attacker calculates the root path of the server they can replace the UWSGI file which runs as root or and other files on the server.
The mitigation against this attack has been well-explained in Flask file upload documentation. You should always rename the files coming from clients and assign random strings to filenames strictly.
Applications that run on the browser have most common attack vectors of cookies. Let’s discuss all the options in Flask and Flask extensions such as Flask-Login and Flask-WTF to protect against cookie attack vectors
We should always use HTTPS rather than HTTP. Nowadays it’s not a big issue to use SSL. We have to add these lines to protect against cookie attack vectors in our Flask configuration.
This will send the cookies over SSL encrypted wire rather than plain text. If an attacker on the same network tries to sniff the network, they will never get the plain text cookies and so these can never be stolen with XSS.
We have to use proper HTTP headers to protect our apps. There are some HTTP headers which can be used to implement some sort of security.
You can set these according to your app but we will mention those headers so you know which HTTP headers to use in case you develop an app. Below is the configuration to set an HTTP header and its value in the response.
- Content-Security-Policy (CSP)
- Strict-Transport-Security (HSTS)
- Public-Key-Pins (HPKP)
As we see, it does not take a lot of time and effort to set up security options in Flask application. Security should always be the main consideration. A low priority bug can be turned into high priority and can cause a lot of harm to your application.