Question

Django: Screening dangerous characters from text input

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?
 2  41  2
1 Jan 1970

Solution

 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.

2024-07-23
Lord Elrond