5 ways to make Django Admin safer
For a better reading experience, check out this article on my website.
With great power comes great responsibility. The more powerful your Django admin is, the safer it should be.
In this article I present 5 ways to protect the Django Admin from human errors and attackers.
Change the URL
Every framework has a fingerprint and Django is no exception. A skilled developer, an attacker or even a tech savvy user can identify a Django site by looking at things like cookies and auth URLs.
Once a site is identified as a Django site, an attacker will most likely try /admin.
To make it harder to gain access we can change the “recommended” URL to something harder to guess.
In the base url.py of the app, register the admin site under a different url:
urlpatterns += i18n_patterns(
url(r’^super-secret/’, admin.site.urls, name=’admin’),
)
Change “super-secret” to something you and your team can remember and you are done! This is definitely not the only precaution you should take, but it is a good start.
Visually distinguish environments
Users and admins are not perfect and mistakes happen. When you have multiple environments such as development, QA, staging and production, it’s not unlikely for an admin to perform a destructive operation in the wrong environment by accident (just ask gitlab).
To reduce the chance of mistakes, we mark different environments clearly in the admin:
First you need to have some way of knowing which environment you are on. We have a variable called ENVIRONMENT_NAME we populate during deployment. We have another variable called ENVIRONMENT_COLOR for the indicator color.
To add the environment indicator to every page in the admin, override the base admin template:
# app/templates/admin/base_site.html{% extends “admin/base_site.html” %}{% block extrastyle %}<style type=”text/css”>
body:before {
display: block;
line-height: 35px;
text-align: center;
font-weight: bold;
text-transform: uppercase;
color: white;
content: “{{ ENVIRONMENT_NAME }}”;
background-color: {{ ENVIRONMENT_COLOR }};
}
</style>{% endblock %}
To make the ENVIRONMENT variables from settings.py
available in the template we use a context processor:
# app/context_processors.pyfrom django.conf import settingsdef from_settings(request):
return {
'ENVIRONMENT_NAME': settings.ENVIRONMENT_NAME,
'ENVIRONMENT_COLOR': settings.ENVIRONMENT_COLOR,
}
To register the context processor add the following in settings.py
:
TEMPLATES = [{
…
'OPTIONS': {
'context_processors': [
…
'app.context_processors.from_settings',
],
…
},
}]
Now when you open Django Admin you should see the indicator on top.
Name your Admin site
If you have multiple Django services that look the same, admins can easily get confused. To help admins be more aware of where they are, change the title:
# urls.pyfrom django.contrib import adminadmin.site.site_header = ‘Awesome Inc. Administration’
admin.site.site_title = ‘Awesome Inc. Administration’
And you get:
For more exotic options look around in the docs.
Separate the Django Admin from the main site
Using the same codebase you can deploy two instances of the same Django app — one only for the admin and one only for the rest of the app.
This is controversial and not as easy as the other tips. The implementation is dependent on the configuration (e.g. if you are using gunicorn or uwsgi) so I won’t go into the details.
Some reasons you might want to split the admin to its own instance are:
- Deploy the admin inside a VPN (virtual private network) — If the admin is used only internally and you have a VPN it is good practice to have it inside the private network.
- Remove unnecessary components from the main site — For example, the Django admin uses the messages framework. If the main site does not, you can remove that middleware. Another example is authentication — if the main site is an API backend using token authentication, you can remove a lot of templates configuration, session middleware, etc. and trim some fat from the request-response cycle.
- Stronger authentication — If you want to strengthen the security of Django Admin you might want to provide a different authentication mechanism just for the admin. This is much easier on different instances with different settings.
We split the admin from the main site only in public facing sites. We don’t bother with internal apps because it complicates the deployment and it has no benefit of being more secure.
Add Two Factor Authentication (2FA)
Two factor authentication became very popular lately as many sites started offering this option. 2FA performs authentication using two things:
- Something you know — Usually a password.
- Something you have — Usually a mobile app that generates a random number every 30 seconds (such as Authenticator by Google).
On first signup the user is usually asked to scan a barcode with the authenticator app. After this initial setup the app will start generating the one-time codes.
I don’t usually recommend third party packages, but a couple of months ago we started using django-otp to implement 2FA in our admin site and it’s working great for us. It’s hosted on Bitbucket so you might have missed it.
The setup is pretty simple:
pip install django-otp
pip install qrcode
Add django-otp to the installed apps and the middleware:
# settings.pyINSTALLED_APPS = (
...
‘django_otp’,
‘django_otp.plugins.otp_totp’,
...
)...MIDDLEWARE = (
...
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
‘django_otp.middleware.OTPMiddleware’,
...
)
Name the issuer — this is the name users will see in the authenticator app, so make it distinguishable.
# settings.pyOTP_TOTP_ISSUER = ‘Awesome Inc.’
Add 2FA authentication to the admin site:
# urls.pyfrom django_otp.admin import OTPAdminSiteadmin.site.__class__ = OTPAdminSite
Now you have a secure admin page that looks like this:
To set up a new user create a “TOTP Device” from the Django Admin. Once you are done click the QR link and you will get a screen like that:
Have the user scan the QR code with the authenticator app on their personal device, and they will have a fresh code generated every 30 seconds.
Final words
Making a Django admin safer and more secure doesn’t have to be hard — you just have to pay attention. Some of the tips mentioned here are very easy to set up and they go a long way.
For more Django Admin gems check out
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!