This article is part of a series on security acronyms every Django developer should know.
Today, we will look at an essential building block for running a secure website: HTTPS. We won’t go into the technical details of the protocol itself, but look at some security measures around HTTPS you should take to keep your users secure.
But first, let’s define what we are talking about: HTTPS stands for Hypertext Transfer Protocol Secure. How does HTTPS differ from HTTP? When using HTTP, data is transmitted in plaintext and anyone on the same network (e.g. an unencrypted Wifi) can eavesdrop the transmission. When using HTTPS, the data is encrypted, thus providing confidentiality of the data. Note that HTTPS does not stand for HTTP over SSL. In the past, SSL was used for encryption, but nowadays TLS is used for encryption.
Confidentiality is only one of the benefits HTTPS provides. The second benefit is that HTTPS ensures integrity: when the client establishes a connection to the server, the server has to provide a certificate that can be used to determine if the server is actually the one it claims to be.
How does the client know if the certificate a server provides is valid? The client, e.g. a web browser, is shipped with a collection of certificates that the browser manufacturer considers trustworthy. Those certificates are called root certificates. When you buy an SSL certificate, it is signed by a certificate authority. The certificate of the certificate authority might be signed by another certificate authority. This chain goes on until the browser encounters a certificate it considers trusted or the chain ends. If there is no trustworthy certificate in the chain, the browser displays a warning.
It is worth mentioning that this goes both ways: the server can also require the client to provide a certificate, but this feature is less commonly used.
Why you should use HTTPS for everything
HTTPS comes at a cost. SSL certificates usually cost money and encrypting the data requires computing power. In the past, these costs could be prohibitive, the former for small-scale side-projects and the latter for large-scale enterprises.
As a consequence, many websites didn’t use SSL at all or only especially sensitive pages like a login page.
In 2017, this is no longer acceptable. There are several ways to get a free SSL certificate, e.g. using Let’s Encrypt. Computing power has become so cheap, that the overhead of encrypting all traffic is usually negligible.
Furthermore, Google has started to penalize sites that don’t use HTTPS. So if you need a good argument to convince your pointy-haired boss that setting up HTTPS is a good idea, just mention that it is good for SEO.
How to enforce HTTPS
Now that you are convinced that you should use HTTPS, how do you make sure that your users only access your site through HTTPS?
You could try to tell your users to always type https:// in the browsers address bar, but the majority of your users will probably ignore this advice.
Therefore, the first step is to redirect all HTTP requests to the equivalent URL using HTTPS. This is best done in your webserver configuration.
But what happens when the initial HTTP request is intercepted by an attacker? A common scenario where this is entirely realistic is that a user is connected to an unencrypted public Wifi.
To reduce this risk, you can implement HSTS. HSTS stands for HTTP Strict Transport Security and is a mechanism to make sure that a browser only accesses your website using HTTPS. Technically, HSTS is quite simple. The server sends an HTTP header to tell the browser to only access the site through HTTPS in the future until the expiration time is reached.
Any future HTTP requests to your site are automatically rewritten by the browser to use HTTPS. This applies when a user types the address of your site in the address bar, a resource on your page, e.g. an image is referenced with an HTTP URL or the user follows an HTTP link from a third-party site. Optionally, this policy can also be applied to all subdomains.
You might wonder what happens when the first access to a site is done via HTTP. The browser doesn’t know yet that the site uses HSTS and has to trust the HTTP connection on first use. To close that loophole, you can add your site to the Chrome HSTS preload list. Don’t let the name deceive you, it is actually used by all major browsers to determine if a site should be loaded by HTTPS.
A word of warning is in order: once the browser encounters an HSTS header, there is no way for the server to take it back until it is expired. If for some reason you decide that you have to disable HTTPS, every browser that has previously encountered the HSTS header will refuse to connect to your site. This means you have to be really sure that your site runs with HTTPS. If you apply it to all subdomains, make sure you don’t forget some obscure internal tool on a subdomain that still uses HTTP.
HSTS definitely improves the security for your users, just be thoughtful about setting it up.
As mentioned earlier, the authentication provided by HTTPS relies on a chain of trust. The certificate of a site is trusted because it was signed by a trusted certificate authority. But what happens when a certificate authority turns rouge or gets sloppy with their verification procedures and hands out certificates to someone else.
To prevent this, HPKP was invented. It stands for HTTP Public Key Pinning and allows a site to specify which certificates are valid for it. HPKP never really caught on and there are currently discussions to deprecate it because it has some disadvantages:
- it can be tricky to set up
- your website becomes inaccessible if you lose all keys
- a hacker could hack your site, create a valid key for it and pin it with HKPK. Then he removes the key and demands a ransom to make your site usable again
My recommendation is not to bother with HPKP right now and to watch the discussion about its deprecation.
By default, the browser always sends cookies for a site and doesn’t differentiate between HTTP and HTTPS. This means that although a cookie might initially be set by the server over a secure HTTPS connection, the browser might send it later via HTTP unencrypted.
To prevent this, you can mark a cookie as secure. Secure cookies are only sent via HTTPS by the browser.
HTTPS & Django
By now, I have hopefully convinced you to set up HTTPS, HSTS and Secure Cookies. How do you do that with Django?
It is important to understand that Django itself doesn’t directly deal with HTTPS – that is the job of the web server. But although you don’t configure your keys and certificates in Django, there are still a bunch of Django settings that are related HTTPS.
Redirecting HTTP to HTTPS
I’d recommend to set up the redirect from HTTP to HTTPS in your web server configuration. This ensures that requests that are handled by your webserver (e.g. static content) are redirected as well and it takes a tiny bit of load from your Django app.
That being said, you can also configure Django to redirect all HTTP requests to HTTPS. Simply set the setting
SECURE_SSL_REDIRECT to True.
There are two settings related secure cookies:
If you set them to True, the corresponding cookie will be marked as secure and the browser won’t send it when making an HTTP request.
That also implies that sessions won’t work with
SESSION_COOKIE_SECURE = True and that CSRF verification will fail when doing a POST request via HTTP when
CSRF_COOKIE_SECURE = True.
But you are redirecting all traffic to HTTPS anyway, so this isn’t an issue for you, right?
You can enable HSTS by setting
SECURE_HSTS_SECONDS and optionally also
Alternatively, you can configure your web server to add the required header. This has the advantage that it also covers parts of your website that are not served by your Django application, e.g. static files.
I hope I could shed some light on HTTPS and some of the related acronyms. If you have any questions, feel free to leave a comment, reach out on Twitter or drop me an email.
This article wraps up the series on security acronyms every Django developer should know. We’ve covered CSRF, XSS, CORS, SOP, HTTPS, HSTS and HPKP. Obviously, this list is far from comprehensive, but it gives you a solid base to expand on.