2

I have a Django app where a few of the forms support a text input with maximum lengths of either 50 or 250 characters. In all cases, the data entered will be stored in the backend DB and will be available for later viewing upon request. In all cases, I'm using the cleaned_data() method when collecting user inputs from the form. And in all cases, the data is such that most "special characters" are unnecessary. (There are a few I'd like to allow for convenience & flexibility, such as hyphens or parentheses, but beyond that alphas & digits should cover it.)

Given all that, I'm looking to put an extra layer of screening on these fields to prevent injections. Particularly XSS but other malicious input as well. I'm thinking the simplest approach is to block/reject the more dangerous characters -- angle brackets, curly braces, and forward/backslashes being the most obvious. My questions are:

  • Are there any other characters I should block/reject to guard against injection attacks?
  • Or, would I be better off going the whitelist route instead? Define the full set of permissible characters and reject anything not in the list?
  • Or -- is this whole idea of field-by-field screening via my own custom methods a sound one? Is there some Django/Python library I could leverage instead to do this checking vs. rolling my own?
6
  • What is the text input is being used for? Commented Jul 22, 2024 at 20:51
  • It's storing information about names of customers, software products they've been sold, etc. Commented Jul 23, 2024 at 0:53
  • 1
    if you have many cases of rejection, you could use regex expression, I think it will catch what you wanna achieve simply and efficiently, and you could make RegexValidator in django for this approach Commented Jul 23, 2024 at 9:13
  • 1
    For the most part if you don't mark random strings as "safe" Django will automatically take care of escaping all "dangerous" characters for you. Yes, you might end up storing those in your database but when you render them out on the template they'll be escaped (and well be very obvious that someone tried to attack your app). Commented Jul 24, 2024 at 5:54
  • 1
    One thing you'd still need to make sure of is to quote all of your HTML elements properly and also to not render anything into JavaScript. For example class={{some_var}} is dangerous because the user could use that to set other attributes as well. Commented Jul 24, 2024 at 6:27

1 Answer 1

1

You should use the Content-Security-Policy header. If configured correctly, the CSP header will prevent the vast majority of xss vulnerabilities.

django-csp provides convenient way to implement CSPs in Django:

# settings.py

from csp.constants import SELF

CONTENT_SECURITY_POLICY = {
    "DIRECTIVES": {
        "default-src": [SELF],
    }
}

MIDDLEWARE = [
    'csp.middleware.CSPMiddleware',
    'django.middleware.security.SecurityMiddleware',
    ...
]

I usually start with default-src 'self' (which prevents loading any resource not on your server), then allow loading external resources as needed. For example, if you are serving stylesheets using a cdn, your CSP would be:

CONTENT_SECURITY_POLICY = {
    "DIRECTIVES": {
        "default-src": [SELF],
        "style-src": [SELF, "https://some.cdn.net"],
    }
}

Be warned: Security headers can be frustrating to implement. You'll need to do some research to determine which policies should be set.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't have time to finish answering your question. I'll add an edit later.
Thanks, I already did some getting up to speed on that and I have a CSP in place. Because I'm using HTMX, I had to open up some windows beyond the fully locked-down policy I would've preferred. I wouldn't mind some guidance on crafting an optimum policy for my project but that's a separate question... and besides, it turns out this one's a duplicate and being closed anyway. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.