Set Up Content Security Policy using Flask Talisman

Content Security Policy (CSP) is an extra layer of security for web applications that secures the application from malicious attacks. CSP instructs the browser on what resources are allowed to load on a specific webpage. Usually, the website administrator configures a CSP by adding a special header to the server’s response for a webpage, then the browser receives the CSP header and understands what resources are allowed to load. At last, if the browser encounters resources attempting to load from an unauthorized source, it blocks the resource to prevent a potential attack.

Talisman is an extension for Flask that simplifies the process of adding CSP to Flask applications.

In this article, we are going to secure our Flask web application by applying CSP using Talisman which is going to make the application more resilient towards attacks like cross-site scripting (XSS) and clickjacking.

Real-World Scenarios of CSP Vulnerabilities

1. Let’s assume, a user visits a legitimate website that allows users to post comments. An attacker uses this opportunity to post a comment with malicious JavaScript code that steals a user’s session cookies.

  • Without CSP, the malicious code will be executed whenever the user views the comment. This can lead to session hijacking and unauthorized access to user’s accounts. This particular kind of attack is known as Cross-Site Scripting (XSS) Attack.

2. The solution to this is implementing CSP with strict script-src directives that only allow scripts from trusted sources this prevents the execution of malicious scripts injected via user-generated content.

3. Let’s assume, a user submits sensitive information, such as bank details on a web form. An attacker intercepts that request and injects additional fields containing malicious data, such as hidden iframe loading a phishing page.

  • Without CSP, the malicious will be executed which can cause data theft and exploitation of the user’s session. This particular kind of attack is known as Data Injection Attack.

4. The solution to this is implementing CSP with strict frame-ancestors directives that only allow loading resources from domains preventing Data injections and mitigating the risks of similar attacks.

5. Let’s assume, an attacker creates a malicious website overlaying a legitimate website, such as a banking website which tricks the user into unintended actions such as transferring funds.

  • Without CSP, the attacker can use the <iframe> element to embed the legitimate website within their malicious page, leading users to perform actions on the legitimate website. This particular kind of attack is known as Clickjacking Attack.

6. The solution to this is implementing CSP with strict frame-ancestors directives that deny framing by default preventing the attacker from embedding legitimate website within a malicious page.

Apply Content Security Policies to Your Flask Application

In this section, we are going to apply CSP to our Flask application to mitigate certain types of attacks such as XSS, data injection, and clickjacking attacks while making sure that necessary resources are loaded.

Before we begin, make sure to follow the steps in the sections Deploy Vultr Optimized Cloud instance, Set up a Python Virtual Environment, and Add Your Demo Application Code Files in our previous article Deploy Flask Applications on Vultr using Gunicorn.

1. Install the talisman Python package.

(myenv) $ pip install talisman

2. In the sample directory, open the app.py file.

(myenv) $ nano app.py

3. Import the Talisman module at the start of the file.

from talisman import Talisman

4. Add the CSPs before the routes in app.py.

talisman = Talisman(

    app,

    content_security_policy={

        'default-src': [

            '\'self\'',

        ],

        'script-src': [

            '\'self\'',

            '\'unsafe-inline\'',

            'https://code.jquery.com',

        ],

        'style-src': [

            '\'self\'',

            '\'unsafe-inline\'',

            'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css',

            'https://todoapp5.ddns.net/static/styles.css',

            'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css',

        ],

    },

    force_https=True,

    session_cookie_secure=True,

    frame_options='DENY',

)

5. The above code sets up a Content Security Policy for our Flask application using the flask-talisman library. Here’s the section-by-section breakdown of the CSP.

  • default-src: Specifies the default sources that are allowed to load the resources in our case only resources from the same origin are allowed by default.
  • script-src: Specifies the allowed sources for loading scripts in our case scripts from the same origin, inline scripts, and jQuery scripts are allowed.
  • style-src: Specifies the allowed sources for loading stylesheets in our case stylesheets from the same origin, inline styles, and styles from bootstrap and a specific stylesheet are allowed.
  • The force_https=True option forces the application to use HTTPS for all requests.
  • The session_cookie_secure=True option ensures that session cookies are only sent over a secure HTTPS connection.
  • The frame_options=DENY option prevents application content from being embedded in an <iframe>.

6. Save and exit the file.

7. For the next steps follow the instructions in the section Create a system service and Configuring Nginx as a Reverse Proxy in our previous article Deploy Flask Applications on Vultr using Gunicorn.

Conclusion

In this article, we used Talisman to apply CSP in our Flask web application. The CSP added a security layer to the application that will help the application against potential malicious attacks.

This is a sponsored article by Vultr. Vultr is the world’s largest privately-held cloud computing platform. A favorite with developers, Vultr has served over 1.5 million customers across 185 countries with flexible, scalable, global Cloud Compute, Cloud GPU, Bare Metal, and Cloud Storage solutions. Learn more about Vultr.