Django XSS Protection Disabled

ID

python.django_xss_protection_disabled

Severity

high

Resource

Misconfiguration

Language

Python

Tags

CWE:80, NIST.SP.800-53, OWASP:2021:A3, OWASP:2021:A5, PCI-DSS:6.5.7, django

Description

Improper configurations or misuse of Django’s templating system can disable XSS protection, exposing applications to cross-site scripting attacks.

Rationale

Cross-Site Scripting (XSS) is a vulnerability that occurs when an application includes untrusted data in a web page without proper validation or escaping.

Django’s templating system is designed with built-in protections to prevent cross-site scripting (XSS) vulnerabilities. These protections automatically escape HTML input, ensuring that user-supplied content is not executed as code on the client side.

However, developers may inadvertently disable these protections by marking content as "safe" or bypassing the template engine, increasing the risk of XSS attacks. Some common misconfigurations and practices can lead to such vulnerabilities:

Global Autoescape disabled Setting

Global Autoescape is a feature in Django’s template system that automatically escapes variables when rendering templates. This crucial security measure helps prevent Cross-Site Scripting (XSS) attacks by ensuring that any HTML, JavaScript, or CSS code in user inputs is not executed by the browser.

# Example of disabling autoescape in template settings
TEMPLATES = [
  {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {'autoescape': False},  # FLAW
  },
]

Non Global Autoescape Disabled Settings

These issues are reported with a lower severity degree.

mark_safe

mark_safe is a utility function in Django that marks a string as safe for inclusion in HTML output without escaping. It’s part of Django’s template system and is used to inject existing HTML or JavaScript code into templates.

If user input is marked safe without proper sanitization, it can lead to cross-site scripting attacks by injecting malicious scripts.

from django.utils.safestring import mark_safe

html_content = "<strong>Important:</strong> Read this!"
safe_content = mark_safe(html_content) # FLAW

SafeString

SafeString is a class used internally by Django to indicate that a string is safe for HTML output, meaning it should not be auto-escaped by the template engine. It’s how Django keeps track of which strings have been marked as safe (When you use mark_safe, it returns a SafeString instance).

If user input is marked safe without proper sanitization, it can lead to cross-site scripting attacks by injecting malicious scripts.

from django.utils.safestring import SafeString

html_content = "<strong>Important:</strong> Read this!"
safe_content = SafeString(html_content) # FLAW

Custom Filter

In Django, custom template filters can be created to manipulate data in templates. By default, Django auto-escapes filter output to prevent XSS vulnerabilities. However, you can mark a custom filter’s output as safe by setting is_safe=True.

If user input is marked safe without proper sanitization, it can lead to cross-site scripting attacks by injecting malicious scripts.

from django import template

register = template.Library()

@register.filter(is_safe=True) # FLAW
def highlight(value):
    return f"<strong>{value}</strong>"

HTML Magic

The html magic method in Django is used to define how an object should be rendered as HTML. If this method is defined, Django’s template engine will use its return value during HTML rendering, and it will not be escaped.

If user input is marked safe without proper sanitization, it can lead to cross-site scripting attacks by injecting malicious scripts.

class SafeContent:
    def __init__(self, content):
        self.content = content

    def __html__(self): # FLAW
        return f"<strong>{self.content}</strong>"

obj = SafeContent("Hello, World!")
html_output = obj.__html__()

html_safe

The html_safe decorator in Django is used to automatically add an html method to a class. This method indicates that the class’s string representation should be treated as safe HTML, exempting it from auto-escaping in templates.

If user input is marked safe without proper sanitization, it can lead to cross-site scripting attacks by injecting malicious scripts.

from django.utils.decorators import html_safe

@html_safe # FLAW
class HtmlContent(str):
    pass

content = HtmlContent("<em>Safe HTML Content</em>")

Remediation

Carefully review every issue addressed by this detector to ensure that the unescaped HTML code is safe.

To effectively address XSS vulnerabilities when using Django enable all the autoescape settings.

References