DEV Community

loading...
Cover image for 20% of Django websites are vulnerable to these 3 hacks

20% of Django websites are vulnerable to these 3 hacks

Django Doctor
I'm a bot that improves your code
Updated on ・3 min read

Django Doctor audits code and auto fixes Django anti-patterns. We checked 666 Django projects for insecure settings.py configurations and were shocked that 20% of the Django websites had these vulnerabilities:

  • 8% had not activated SecurityMiddleware read more
  • 6% were vulnerable to clickjacking read more
  • 5% were vulnerable to CSRF attack read more

Django docs suggests SecurityMiddleware is placed near the top of your MIDDLEWARE settings for good reason: it performs a suite of security checks and enhancements that would otherwise leave your website to the mercy of some simple hacks.

How would you solve these security flaws? Try our Django security challenge.

Clickjacking

Clickjacking is an attack where one of your logged-in user visits a malicious website, and that website tricks the user into interacting with your website via an invisible iframe (which in the demo I made mostly transparent otherwise you would see nothing interesting):

See my previous post for more details and working proof of concept

Cross Site Request Forgery

A malicious website that is accessed by one of your logged in users can fool your website into thinking a request come from that user. That may look like this:

  1. The user accesses the malicious website
  2. The website executes JavaScript to perform a request to your website
  3. The browser exposes the user's cookies to your website
  4. Your website thinks the request came from them

Here's a concrete example of a CSRF attack:

See my previous post for more details and working proof of concept

Tricking Django into executing uploaded javascript

SecurityMiddleware prevenst hackers from tricking your website into executing a malicious javascript file that they uploaded by setting the X-Content-Type-Options header to nosniff.

This header indicate to the browser that the when the MIME types advertised in the Content-Type headers is not present, the browser should not guess it by "sniffing" what the content "smells" like. The browser uses the MIME type to determine to render HTML, execute JS, etc. Sniffing may be a very helpful feature for when servers are misconfigured and do not expose the Content-Type header. But it can be abused, as the following simple proof of concept shows:


# settings.py
MIDDLEWARE = [
    # "django.middleware.security.SecurityMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    ...
]

SECURE_CONTENT_TYPE_NOSNIFF = False  # pre-Django 3.0 it was False by default. Post 3.0 it's True

# views.py
class HomePage(View):
    def get(self, *args, **kwargs):
        # simulate a misconfgured server that returns a response that has no content type
        response = HttpResponse("<script>alert('hello world')</script>")
        del response['Content-Type']
        return response
Enter fullscreen mode Exit fullscreen mode

The outcome when navigating to HomePage shows the "hack" worked:

Alt Text

Such attacks can be avoided if the SecurityMiddleware is present and the nosniff feature is active:

# settings.py
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    ...
]

SECURE_CONTENT_TYPE_NOSNIFF = True
Enter fullscreen mode Exit fullscreen mode

Then the browser does not fall for the trick:

Alt Text

User privacy

Would you be happy if every hyperlink you clicked on told the target what website you came from? Aside from the privacy aspect, this leaks information to potential bad actors (e.g, if the url contained private information).

SecurityMiddleware sets the referer policy header based on SECURE_REFERRER_POLICY, which impacts user privacy and it leaks information for bad actors to abuse.

Is your Django code insecure?

Over time it's easy for security vulnerabilities to slip into your codebase. I can check that for you at django.doctor, or can review your GitHub PRs:

Alt Text

Or try out Django security challenge.

Discussion (0)