Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon

How to Use TLS Securely in Flask Applications

Save for later
View related Packt books & videos

article-image

Introduction

There is a lot of documentation and some books you can find on the TLS protocol and the theory behind it. But what do you do when you actually have to deploy TLS in a real-world application? For example, what do you do to enable TLS for your web application written in Flask? Securing web applications is more important than ever, and Transport Layer Security (TLS) plays a vital role in protecting data in transit. For developers using Flask, a popular Python web framework, implementing TLS might seem daunting. This article provides a practical guide to setting up TLS for Flask applications, focusing on Nginx as a reverse proxy, secure configurations, and avoiding common pitfalls. Whether you're a beginner or an experienced developer, you'll find actionable insights to ensure your application is both performant and secure.

TLS and Flask

If you want to write a web application, chances are you'll end up using Flask, a popular microweb framework written in Python. Flask is well-known for its simplicity, flexibility, performance, and beginner-friendly learning curve.

 Flask is a WSGI (Web Server Gateway Interface) application, where WSGI is a standard interface between web servers and Python web applications or frameworks. Finally, a WSGI application is a Python callable that accepts two arguments environment and start_response, and returns an iterable, allowing it to handle HTTP requests and responses in a standardized manner. In Flask, a WSGI server runs the application, converting incoming HTTP requests to the standard WSGI environment, and converting outgoing WSGI responses to HTTP responses. 

When deploying your Flask application to production, the Flask documentation strongly recommends using a dedicated WSGI server rather than the built-in development server.

WSGI servers have HTTP servers built-in. However, when serving your application with a WSGI server, it is good practice — and might be even necessary depending on the desired configuration — to put a dedicated HTTP server in front of it. This so-called “reverse proxy” handles incoming requests, TLS, and other security and performance concerns better than the WSGI server.

The Flask documentation describes how to set up Nginx as a reverse proxy. The documentation also provides the following example configuration, but the example does not include TLS support. 

 server {
    listen 80;
    server_name _;
 
    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Prefix /;
    }
} 

So, what do you have to do to enable TLS? In Nginx, TLS and, thus, HTTPS support is provided by a dedicated module called module ngx_http_ssl_module which itself relies on the well-known cryptography library OpenSSL.

Here’s an example TLS configuration given in ngx_http_ssl_module documentation

worker_processes auto;
 http {
 
    ...
 
    server {
        listen              443 ssl;
        keepalive_timeout   70;
 
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        ssl_certificate     /usr/local/nginx/conf/cert.pem;
        ssl_certificate_key /usr/local/nginx/conf/cert.key;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;
 
        ...
    } 

But wait, what about insecure TLS configurations? How do you know that your setup will hold off the bad guys?

To help you with this task, we wrote a small script which you can download at https://github.com/TLS-Port/TLSAudit. The script reads TLS configuration options in a given Nginx configuration file and prints a warning for any weak or insecure TLS options. We believe the script is helpful because Flask documentation refers also to older OpenSSL versions down to 1.0.2, which reached its official end of life by the end of 2019. These old OpenSSL versions contain algorithms with known cryptographic weaknesses.

 In the remainder of the article, we want to highlight three important TLS parameters that are checked by the script.

TLS Ciphers

The ssl_ciphers ciphers directive specifies the enabled ciphers in a format understood by the OpenSSL library, for example:

ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;

The full list of available ciphers can be obtained using the openssl ciphers command. However, not all ciphers supported by OpenSSL are considered secure. Nginx documentation recommends the use of OpenSSL 1.0.2 or higher. Ciphers that should be avoided include:

  • RC4: A stream cipher which is known to be vulnerable for a long time, irrespective of the key length. 
  • DES and 3DES: DES is very old cipher whose effective key length is way too short (56 Bit). The 3DES, or TripleDES applies the DES three times. It has a larger key space, but is quite ineffective.
  • MD5-based Cipher Suites: MD5 is a broken hashing algorithm susceptible to collision attacks. Its use weakens the overall security of the whole cipher suite.
  • Export-grade ciphers: Export-grade ciphers -- usually, they have an EXP in their name -- were intentionally weakened (to 40 or 56 bits) to comply with export restrictions from the 1990s. These ciphers are highly vulnerable to brute-force attacks.

Early data in TLS 1.3

The ssl_early_data directive enables or disables so-called early data in TLS 1.3. If two TLS endpoints share a secret key (this is called a pre-shared key, or PSK), TLS 1.3 allows them to communicate over a secure channel right from the start. This is referred to as zero round-trip time (0-RTT) mode which was added in TLS 1.3. It reduces TLS latency by allowing client Bob to send data to server Alice in the first round-trip, without waiting for Alice’s response. Bob uses the shared key to authenticate the server and to establish a secure channel for the early data which is simply added to the standard 1-RTT handshake.

 The downside is that 0-RTT data is less protected. First, forward secrecy does not hold for this data because it is encrypted using keys derived from the PSK rather than fresh, randomly generated key shares. This means that if the PSK gets stolen, earlier recorded TLS session can be decrypted by the attacker.

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime

Second, 0-RTT data is not protected against replay attacks, where legitimately encrypted and authenticated data are recorded by an attacker and replayed into the communication channel. Regular TLS data is protected against this type of attack by the server’s random variable. 0-RTT data, in contrast, does not depend on the ServerHello message and therefore lacks fresh randomness from the server. Enabling early data can, therefore, decrease TLS security.

 Elliptic Curves

The ssl_ecdh_curve directive specifies one or more so-called elliptic curves used in Elliptic Curve Diffie Hellman ephemeral (ECDHE) key agreement. Unfortunately, there are some elliptic curves in OpenSSL 1.0.2 which are insecure according to today's standards:

  • SECP192R1 (prime192v1 or P-192)
  • SECP224R1 (P-224)
  • SECP160R1 and SECP160K1
  • Brainpool curves with a number less than 256

TLS version

The ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3] directive specifies the TLS versions supported by the reverse proxy. 

 As already discussed, SSLv2 and SSLv3 versions contain serious known security weaknesses and must not be used. But also for TLS versions 1.0 and 1.1 there are known attacks that were shown to work in practice. So, only TLS versions 1.2 and 1.3 should be used (and the former with care).

Naming: SSL or TLS?

Let's get things straight. Practically everybody surfing the web today uses web addresses starting with https, which stands for Hypertext Transport Protocol Secure. The Secure part is realized by a cryptographic protocol called Transport Layer Security, or TLS for short. SSL, on the other hand, refers to initial TLS versions dating back to early 1990s.

To address security needs of the upcoming e-commerce, Netscape Communications started designing a new protocol they named Secure Sockets Layer (SSL) for establishing a secure channel between a web server and a web browser. SSLv1, the first version of the SSL protocol, had severe security issues and Netscape never released its specification or implementation. 

In November 1994, Netscape publicly released SSLv2, the second version of the SSL protocol, and integrated into Netscape Navigator 1.1 in March 1995. Soon after its release, however, a number of further security weaknesses were discovered in SSLv2. Learning from these flaws, Netscape re-designed SSL from scratch and released SSLv3 in late 1995.

In May 1996, the Internet Engineering Task Force (IETF) formed a working group to standardize an SSL-like protocol. The standardization process took around three years and the TLS 1.0 standard was published as RFC 2246 in January 1999. While TLS 1.0 closely resembled SSLv3, it had no backward compatibility to SSLv3. 

Almost seven years later, in April 2006, IETF published RFC 4346 defining the successor TLS version 1.1. Publication of RFC 5246 and with it a new version TLS 1.2 followed in 2008. Finally, in August 2018, IETF published RFC 8446 which specifies the newest TLS version, TLS 1.3.

Conclusion

Securing your Flask application with TLS is essential for protecting sensitive data and building user trust. By following the best practices outlined in this article—such as configuring strong ciphers, enabling secure TLS versions, and leveraging tools like TLSAudit—you can ensure a robust, production-ready setup. For a deeper dive into the intricacies of TLS and advanced cryptographic concepts, consider exploring the book TLS Cryptography in Depth, by Dr. Paul Duplys, Dr. Roland Schmitz. TLS is the most important and widely used security protocol in the world. This book takes you on a journey through modern cryptography with TLS as the guiding light. It explains all necessary cryptographic primitives and how they are used within TLS. You’ll explore the inner workings of TLS and its design structure.

how-to-use-tls-securely-in-flask-applications-img-0

Author Bio

Dr. Paul Duplys is chief expert for cybersecurity at the department for technical strategies and enabling within the Mobility sector of Robert Bosch GmbH, a Tier-1 automotive supplier and manufacturer of industrial, residential, and consumer goods. Previous to this position, he spent over 12 years with Bosch Corporate Research, where he led the security and privacy research program and conducted applied research in various fields of information security. Paul's research interests include security automation, software security, security economics, software engineering, and AI. Paul holds a PhD degree in computer science from the University of Tuebingen, Germany.

Dr. Roland Schmitz has been a professor of internet security at the Stuttgart Media University (HdM) since 2001. Prior to joining HdM, from 1995 to 2001, he worked as a research engineer at Deutsche Telekom, with a focus on mobile security and digital signature standardization. At HdM, Roland teaches courses on internet security, system security, security engineering, digital rights management, theoretical computer science, discrete mathematics, and game physics. He has published numerous scientific papers in the fields of internet and multimedia security. Moreover, he has authored and co-authored several books. Roland holds a PhD degree in mathematics from Technical University Braunschweig, Germany.