The software world is moving to the web. Businesses, services, and products are all moving to web applications due to the reach and accessibility of web apps. With this major migration, web application frameworks have improved and become more powerful than ever. But there’s a challenge: security. With a majority of businesses conducting transactions online, web applications became a valuable asset, and also became a valuable target for malicious actors. Hence, security became more crucial than ever.
One of the top web application frameworks and a favorite of developers is Django. Django is a Python-based open-source web framework that allows rapid development. And along with scalability, a strong community and a batteries-included framework (loaded with most of the features required for development), Django also focuses on security. In this post, we'll look at some security features and libraries that come built into Django. Then we’ll see how its security features protect against common web attacks. And finally, we’ll go over some best practices for your Django projects
Django Security Features
Escaping Dangerous Characters
Django has some built-in features that handle user-submitted data to make it safe for an application. These features escape possible dangerous characters in requests, making the data safe for the application to use.
The first rule of web application security is to never trust user-submitted data. Of course, the majority of the data you receive from the user side will be legit and safe. But an attacker can also maliciously craft data to damage your application or system. For example, if your application uses a SQL database and executes queries based on user input, a malicious actor can craft input that executes a query it's not supposed to. And malicious data from the user side means more than data entered in user input fields, like in forms. An attacker can also manipulate web requests, and Django’s got that covered too.
Clickjacking Protection
Clickjacking is a technique in which a malicious actor tricks a user into clicking on something other than what the user intends to. So how does this happen? One of the common ways is by placing a malicious web element or page in a legit web page using iframe. For example, when a user tries to click on a button, they'd end up clicking on a malicious button on a different page altogether.
Django provides clickjacking protection in the form of X-Frame-Options middleware. This feature prevents a different site from rendering inside a frame.
Enforcing SSL/HTTPS
Encryption is important to keep data secure. Django has encryption features that help you enforce secure connections. Some of these features are:
Redirect HTTP requests over HTTPS
Send cookies only over HTTPS connection
These are some of the main security features for Django applications. Although these cover the basics, you'd need more security practices as per your use case. So along with the default security features, you can bring in security libraries to make your security better.
Security Libraries for Django
Django is based on Python, and Python is very well known for its huge collection of libraries that meet almost every need. It has many libraries to improve the security of your Django applications. Here's a brief list of some security libraries for Django:
Secure Auth: Provides secure authentication (multi-factor authentication, or MFA) with a time-based one-time password (TOTP), short message service (SMS), security codes and question–answer pairs. You can further improve login authentication with IP ranges and captcha.
Django Defender: Blocks brute-force login attempts.
Django Session Activity: Helps identify suspicious and malicious behavior by listing recent account activity and sign-outs from all sessions opened on computers.
Restricted Sessions: Restricts Django sessions to the IP address and/or user agents it authenticates. So if the IP or user agent changes after creating the session, the request receives a 400 response, and the session gets flushed.
Django Rules: Provides object-level permissions for Django.
Admin Honeypot and Django Honeypot: Help create decoys to identify malicious activity.
Django Cryptography: Encrypts data.
Now let's look into some of the most common attacks and how Django security features protect against them.
Common Django Security Attacks
Common attacks on Django applications are mostly the same as the common attacks on any web app framework, because the tools and general processes for particular attacks are the same for all frameworks.
Although you might find attacks specific to Django, these are relatively few. Now, let's go through different attacks and see how Django fights against them.
SQL Injection
SQL injection is when an attacker injects crafted SQL queries into a request. The attacker attempts to make the application execute a query that it ideally would not. Two main criteria for a SQL injection to work are
the application uses a SQL database, and
user-submitted data is part of the SQL query.
The main source of threat for a SQL injection is user-submitted data that the underlying SQL query uses as a parameter. Django SQL injection protection uses query parameterization. You can divide a complete SQL query into SQL code and query parameters. The application carefully escapes any data it uses as a parameter to make it safe.
Cross-site Scripting (XSS)
An XSS attack is a technique wherein a malicious actor injects crafted malicious client-side scripts into an application to manipulate the application's functions. The origin of an XSS attack is an untrusted source of data. Django XSS protection uses the concept of templates to prevent XSS attacks. By default, Django templates escape special HTML characters in the HTML code to prevent XSS attacks. For example:
< is converted to <
> is converted to >
‘ (single curly quote) is converted to ' (single straight quote)
“ (double curly quote) is converted to " (double straight quote)
& is converted to &
So even when an attacker injects a client-side script, the browser doesn't process it as code. Although this provides a basic level of security, it's not foolproof. You need to take extra measures to make your application more secure.
Cross-site Request Forgery (CSRF)
CSRF is an attack in which an attacker uses the authentication information of a user to trick the authenticated user into performing an action that they don't intend to perform. Django CSRF provides protection against CSRF using its CSRF middleware and creating a secret value, a.k.a CSRF token. A CSRF token is a unique, secret value that is sent to the client-side from the server. And for every subsequent request from the client, the server checks this secret value. This prevents a malicious user from replaying a form POST to your application. For a malicious actor to execute a CSRF attack, they'd have to know the secret value specific to each user.
Open Redirect
An open redirect is a security weakness in an application that occurs when the application uses user-controlled data for redirection. If you don’t check that the user-controlled data is secure, then an attacker can manipulate the data and execute an open redirect attack. Django open redirection protection allows you to run the URL through a safety checker. The is_safe_url() function from django.utils takes a URL as input and checks if it’s safe or not, and blocks the redirection if it finds something unsafe.
Path Traversal
A path traversal attack is when an attacker manipulates a URL or a request to access directories stored outside the permitted directory of the application. This technique mostly relies on the directory structure and a directory reference. For example, if the current directory is /django, an attacker could access the parent directory using ../ (double dots are used to refer to parent directory).
The latest versions of Django provide protection from path traversal attacks by enforcing use of absolute paths. Django uses Python’s os.path.abspath to determine if the absolute path is located in the permitted directory. Or you can use Python's os.path.relpath module to determine the path and compare it with the permitted path.
More Security
As you can see, Django is very security-focused. But is it enough? Absolutely not! When it comes to security, no amount is enough. So along with the built-in features of Django and its security libraries, here are some security best practices to follow.
Use additional encryption. Although Django by default provides encryption features for data flowing over the network, you need to take care of encryption in other parts of the application. For example, you need to encrypt the secret keys that you're using in your application. This is especially useful if you're using version control systems.
Change default URLs to custom URLs. For example, if the default to access an admin page is /admin then change it to something like /my-app-admin-page. This will make it difficult for attackers to find special portals.
Use MFA.
Be careful with Git commit. Make sure not to commit any sensitive data.
Use honeypots to understand what attackers are targeting and what techniques they’re using. Then put extra focus on improving security based on the data.
Continuously test your application for security weaknesses.
Summing It Up
Django is one of the most convenient web application frameworks. You cannot compromise on security in today’s applications. Along with making development easy, Django focuses on security and provides multiple security features by default, and for some other security features, you have to either enable them or configure them. We've explained different security features of Django, additional libraries that can enhance security, and best practices for security. They apply to all applications in general, but they’re not enough.
Security is best when it's above the benchmark and custom-tailored for your application. Therefore, once you implement all the basic security practices and fix common weaknesses, you need to focus on application-specific security. This calls for regular monitoring, keeping up-to-date with the latest security weaknesses and fixes, and most importantly security testing.