Django has a security policy right from the developers to the deployment. Django is really and extensible web framework, with it's middleware you can build custom security features to handle common attacks and mitigate them. The life of a web application if it's a living person it would be very stressfull.
Today am going to show you how to build a web application firewall extendable to try and mitigate common web application attacks, this middleware should be place on top of the middleware chain to handle request and process them before they can reach the downstream to be processed by other middlewares. This tutorial is not bullet proof, you have to monitor webserver logs and see what requests including attacks reach your web application.
To fully benefit from and extend this middleware, you have to understand very well the make up of your django application,for example;
- Does your web application accept requests args
- What kind of request does your web application accept(GET, HEAD, POST, DELETE)
- Does your web application handle file downloading?
More analysis is needed and as you gain more knowledge of the make up of your web application you can extend this middleware. Another thing worth understanding is the webserver being used, NGINX, APACHE, kindly watch the logs of this webservers they will help you to better build a more robust web application firewall.
How Django discloses security issues
Our process for taking a security issue from private discussion to public disclosure involves multiple steps.Approximately one week before public disclosure, we send two notifications.cFirst, we notify django-announce of the date and approximate time of the upcoming security release, as well as the severity of the issues. This is to aid organizations that need to ensure they have staff available to handle triaging our announcement and upgrade Django as needed. Severity levels are:
- Remote code execution
- SQL injection
- Cross site scripting (XSS)
- Cross site request forgery (CSRF)
- Denial-of-service attacks
- Broken authentication
- Sensitive data exposure
- Broken session management
- Unvalidated redirects/forwards
- Issues requiring an uncommon configuration option
Writing Middleware to Deal Security Issues in Django application.
Let's begin writing our middleware to handle the security issues in django application. Create the middleware inside a django application of your project for example if you have an app called security or waf(Web application Firewall) then inside that app create a file called middleware.py
After Creating that file now you can added inside your django list of middlewares inside the settings.py
MIDDLEWARE = [ # Since it's going to handle critical security things, let me be the first in list of middleware 'security.middleware.WebApplicationFirewall', ]
Now open middleware.py and add the following piece of Code.
import re from django.conf import settings from django.http import HttpResponse import logging from django.core.cache import cache class WebApplicationFirewall(object): """ This class object will perform filtering of malicious requests directed towards our application in an attempt to exploit it. """ WAF_RESPONSE_CODE = getattr(settings, 'FAKE_BOT_RESPONSE_CODE', 403) # Define list that will hold requests we want to block FILE_EXTENSIONS = [".html", ".htm", ".php", '.asp', '.jsp', '.py', '.sh','.xml', '.gz', '.zip', '.tar'] # Malicious file extension requests that we want to be blocked. # Preferably keep this inside settings.py then # FILE_EXTENSIONS = getattr(settings, 'FILE_EXTENSIONS', ) WRONG_PATHS = ["/login?", "/cgi-bin/", '/.env', '//.env', '/.git/config', '/.hg/requires', '/.svn/entries', '/.bzr/branch-format'] # Malicious path requests directed to our app # Preferably keep this inside settings.py then # WRONG_PATHS = getattr(settings, 'WRONG_PATHS ', ) ANTI_SQL_INJECTION = ["UNION+SELECT+ALL", "UNION+SELECT", "information_schema+AND", "+or+SLEEP", "+SLEEP", 'SELECT * FROM users', 'SELECT * FROM','SELECT *','SELECT',"UNION"] # SQL Injection # Preferably keep this inside settings.py then # ANTI_SQL_INJECTION = getattr(settings, 'ANTI_SQL_INJECTION ', ) def __init__(self, get_response): self.get_response = get_response def __call__(self, request): """ PROCESSING IS DONE HERE """ try: user_agent = request.META.get('HTTP_USER_AGENT') path = request.path query_string = request.GET.urlencode() if(path in self.WRONG_PATHS): return HttpResponse(status=self.WAF_RESPONSE_CODE ) for ext in self.FILE_EXTENSIONS: if(path.endswith(ext) and "sitemap.xml" not in path): return HttpResponse(status=self.WAF_RESPONSE_CODE ) for req in self.WRONG_REQUESTS: if(req in path): return HttpResponse(status=self.WAF_RESPONSE_CODE ) for req in self.ANTI_SQL_INJECTION: if(req in path or req in query_string): return HttpResponse(status=self.WAF_RESPONSE_CODE ) return self.get_response(request) except Exception as e: return self.get_response(request) # This is just a sample of what this simple custom WAF can be like. Again you must understand # the layout and the type of requests your application is expecting.
As you can see it's very simple and easy to write a simple Web application Firewall for django. But the most important thing is you must understand the layout of your django application, the kind of requests it expects.
Alternative to Django Web application Firewall
It is better to use atleast mature web application firewalls. One of those web application firewalls that support django is shadowd
- Shadowd. Shadow Daemon is a collection of tools to detect, record and prevent attacks on web applications. Technically speaking, Shadow Daemon is a web application firewall that intercepts requests and filters out malicious parameters. It is a modular system that separates web application, analysis and interface to increase security, flexibility and expandability. This component can be used to connect Python applications with the background server.
You can install the package with easy_install or pip:
easy_install shadowd pip install shadowd
Finally you can check for web application firewalls of your website by using this online tester.