Insecure or unset HTTP headers - Content-Security-Policy - Python

Insecure or unset HTTP headers - Content-Security-Policy - Python

Need

Implementation of secure and properly configured Content-Security-Policy headers

Context

  • Usage of Python 3 for building and executing Python applications
  • Usage of Django for building web applications in Python

Description

Non compliant code

        from django.http import HttpResponse

def some_view(request):
    response = HttpResponse()
    # Notice the lack of Content-Security-Policy header in the response
    return response
        
        

In the above code snippet, a Django view is defined which returns an HTTP response. However, the response is missing the Content-Security-Policy HTTP header. This header is used to prevent certain types of attacks, like Cross Site Scripting (XSS) and data injection attacks.

By not including this header, or not setting it properly, the application could become vulnerable to these types of attacks. The Content-Security-Policy header allows you to restrict how resources such as JavaScript, CSS, or pretty much anything that the browser loads.

For example, you can set policies to only allow scripts to be loaded from the same origin as the website, or only from specific trusted domains. You can also disable inline JavaScript and CSS to prevent injection attacks. Without this header, or with an insecure value, an attacker could potentially inject malicious scripts or other resources into your web page.

Steps

  • Identify the areas of your application where the Content-Security-Policy (CSP) header is missing or improperly configured.
  • Understand the specific security policies that your application needs. This could include policies for scripts, styles, images, media, frames, etc.
  • Add the Content-Security-Policy header to your HTTP responses. This can be done in the Django view by using the 'HttpResponse' object's 'set_header' method.
  • Define the necessary security policies in the CSP header. Be sure to avoid insecure values. For example, avoid using 'unsafe-inline' or 'unsafe-eval' as these can open up your application to cross-site scripting (XSS) attacks.
  • Test your application to ensure that the CSP header is properly set and that the defined policies are working as expected.

Compliant code

        from django.http import HttpResponse

def some_view(request):
    response = HttpResponse()
    # Set the Content-Security-Policy header
    response['Content-Security-Policy'] = "default-src 'self'; script-src 'self'; object-src 'self'; style-src 'self';"
    return response
        
        

The above code fixes the vulnerability by adding the Content-Security-Policy (CSP) header to the HTTP response. The CSP header is used to prevent Cross-Site Scripting (XSS), clickjacking and other code injection attacks resulting from execution of malicious content in the trusted web page context.

The Content-Security-Policy header is set using the HttpResponse object's dictionary-like interface. The value of the header is a string that defines the security policies.

In this case, the security policy is set to only allow resources (scripts, objects, styles, etc.) from the same origin ('self'). This is a common policy that can help to mitigate the risk of XSS attacks by restricting where resources can be loaded from.

Please note that the specific security policies that you need may vary depending on your application. You should understand the specific needs of your application and set the CSP header accordingly.

After implementing this fix, you should test your application to ensure that the CSP header is properly set and that the defined policies are working as expected.

References