At djangsters we care about security. We care so much about security that the batteries-included approach to it that Django follows is one of the main reasons Django is a fundamental building block for our web apps.
To extend our security portfolio, over the last couple of years we started to work with external security audits in the form of penetration tests (pentests). While this was a new experience for us, we approached it with excitement, and a little skepticism, and come out with three main revelations:
- It is worth it.
- Security is like an onion.
- Configuring Django's security framework correctly gets you very far.
But one step at a time, before we dive in, let's zoom out and look at the overall picture.
There are often three parties involved in a pentest. A development team, an internal regulatory body, and a security testing agency.
The development team is responsible for the code and it is their job to fix any security concerns. The internal regulatory body requires the tests and sets standards, while the security agency finds the problems. So it’s basically a game of cat and mouse with a referee.
It sounds complicated but it's relatively straightforward and easy to grasp once you get started.
For us it went down like this:
- We finished a major upgrade that required that we pass a pentest.
- The time window for the pent test was set at ~ 24 to 48h.
- Each blocking request had to be addressed within 24h.
- We got the detailed report within the next 2 weeks.
- We address the medium and low priority issues until we got the green light.
- Release 🚀
Penetration test reports are usually semi-automatically generated and sort problems into low, medium and high priority categories.
Low priority problems are the nice-to-haves and don’t present a present danger. For example a leaking version string of an involved software. These are typically not blocking and do not prevent a green light.
Medium priority problems are required for the green light and are often not fully strengthened security measures.
High priority or critical problems are exploitable flaws. These MUST be addressed before anything else because they pose a clear and present danger.
Now, here comes the tricky part for every software developer, is a pentest an evaluation of your work? Is every problem reported a condemnation of the quality and a damning finger pointed at it?
Pentest reports are basically just another level of code code review. Those categories and evaluations are an outside and independent view of your work. It might be tempting to use them as just a checklist to get the green but a better approach is to use them as a learning experience.
Some might be not relevant, some might be minor but they all are well intended suggestions on where and how to improve. Of course, at the end of the day, you wrote the code and you know best where the corpses are buried, a pentest just tells you where there is a finger sticking out.
As mentioned before, Django takes security very seriously for the best tip we can give is to go through the Django settings and check them for hardening security settings. Because Django is so awesome and because it is just so easy to miss some weak debug configuration, Django makes it so that you don’t have to guess. There is a security document that has best practices laid out.
Proper release management and usage of environment variables also help, but that is a topic for another time.
A few non-obvious tips that will help you pass:
- Content Security Policy (CSP) Headers - There is a great middleware for it
- Password Policies - Django brings a lot of default options
- Keep your dependencies up-to-date - Tools like dependabot will cover you here.
- Ensure proper rate-limits, timeouts
Let me empathize again on the greatness of not only Django as a framework but its documentation. If there is little time for security hardening, just following the Django security document and ensuring to check and understand all configured settings and their influence in your particular setup, will improve the security of your web application backend to a decent level.
Getting back to our main takeaways. While a decently working development team that uses a decent framework (👋 Django 👋) and takes testing and review seriously will most likely not see critical security issues, there will be a couple of medium ones. Those seem annoying and relatively harmless, a missing CSP header, a theoretical injection vector or a weak password policy, but they can act as a stepping stone for more dangerous attacks.
However, while developing a web application it is almost impossible to have all layers of security in mind. Therefore it is best you focus on the application layer and let the pentester do their job. Their input helps you a lot to harden your overall security approach.
If you are curious about the Whats and the Hows of pentesting, as seen from a pentester's perspective, check out this article from our friends and partners at Lutra Security.