Django security best practices
securing Django applications
Introduction
Django is a powerful web development framework. It sells itself as the web framework for perfectionists with deadlines. And this makes sense, considering it is a framework with batteries included.
The Django project learned from the mistakes made by other content management systems (CMS) and frameworks. So when it comes to security, Django has its defenses in place. This checklist shows the available security capabilities and additional options.
Basics
Securing the system
Application security starts at the system where it is hosted on. When installing a system that is to be used in production, choose for the 'minimal' installation. This only installs the required components to run the system. From there, install the components that are to be used to host the application, like Apache or nginx to serve web requests. When used, add the related database engine like MySQL or PostgreSQL.
Keep a system secure is not that hard, yet it is easy to forget things. A common issue is that systems are not patched, leaving some applications vulnerable for attackers. Especially when using web services, most components will be publically available. So lock them down, reduce their visibility, and patch them. Use automatic security patching when possible. Most Linux distributions have an option available to do this automatically. To be clear, you don't have to automatically patch all components, only those marked with the 'security' flag by the package manager.
- Use the 'minimal' installation option for production systems
- Do not install X Window system on servers
- Turn on automatic security updates (e.g. unattended-upgrade on Ubuntu)
- Perform automated security audits daily (e.g. using Lynis)
Setting up the right disk structure
Every project begins with a structure on the disk. By using django-admin with the startapp or startproject command, the related directory structure is created. The first mistake is around the corner when serving the project via web server software like Apache or Nginx. Any code that is in the 'root' directory of the web server, might be disclosed.
When you set your virtual host configuration to /home/www-user/myproject/project, make sure that any of the code is at least one level higher. This way the web server can't reach it directly (in /home/www-user/myproject).
Configuration
Keeping secrets
A secret should remain secret. Within Django, there is one big secret key that needs to be properly protected. The variable is found in settings.py and goes by the name SECRET_KEY. Preferably it needs to be unique. And as the name implies, it should always be kept secret.
One of the biggest risks is that a secret key is checked into source code repositories by accident. To prevent this, generate a random secret key and overrule it in a separate configuration file. This way it is fine to have settings.py in the repository, while the secrets are stored somewhere else.
import uuid
SECRET_KEY = uuid.uuid4()
Debugging
Django provides several debug options during the development. While great for development, they are a risk in production. The documentation clearly states that the DEBUG variable needs to be set to False. The reason is simple: security controls are disabled when debugging is enabled.
Allowed hostnames
The setting ALLOWED_HOSTS is a list that defines which hostnames are valid for the Django application. To ensure invalid traffic is not accepted by the application, only add the hostnames that are actually used. It might be needed to add 'localhost' or the IP address of the system itself when proxying the traffic.
Code quality
Analyzing source code
The quality of most software depends on its original code. Analyzing the code with static analysis tools is a good option to measure its health. Areas of interest include the code style, usage of variables, and properly checking input. As Django uses the Python programming language, things like PEP8 and linting are good starters.
Code style and linting
The Python community uses PEP, which stands for Python Enhancement Proposals. One of the earliest proposals is PEP 8. It is titled Style Guide for Python Code and goes into what healthy Python code should look like. Although an application may not become more secure of it, readable and healthy code is beneficial. It helps to reduce programming errors which may result in security weaknesses.
To test an application against the style guide, there are several tools available. Most can be easily found within pip. One of the well-known tools is flake8. It combines several techniques to test the style, which is known as code linting.
Additional resources
Suggested projects
For more details about Django security, we recommend OWASP (Open Web Application Security Project) and the Django website.