Anselm Hannemann recently made a post about some of the misconceptions that front-end developers might have about web security. Since I had lots of questions about these things, I thought I'd interview Anselm to get his take on the surprising complexity of getting set up with HTTPS. We talk about things like generating certificates and how we might best make sense of the conflicting opinions many developers, including myself, have about third-party services such as Cloudflare.
For those that aren’t familiar with web security, would you mind describing the differences between HTTP and HTTPS?
Sure! The general difference between HTTP and HTTPS is simple: HTTP, or Hypertext Transfer Protocol, is the default protocol that we use to serve websites and transfer data. However, that information is sent in an unprotected, unencrypted way. HTTPS however combines HTTP and TLS (which is a cryptographic protocol) in order to protect data that is sent over a network by encrypting it.
You may wonder why you would need to encrypt the connection to your website if the content is public anyway. Let’s assume that you use a CMS, like WordPress or Craft, for your website. If you log in over HTTP to your backend, your credentials are sent in plaintext to the server. So, anyone who intercepts your WiFi or internet connection now has access to your CMS (it’s super easy, really – just think of public WiFis in cafés). But not only that, HTTPS can also protect you from getting the wrong content. If HTTPS is set up properly, hackers can’t overtake DNS to serve different content on your domain anymore. With HTTPS it’s also not possible for software on your computer to inject ads or malware into webpages.
You can think of HTTPS as the more secure version of HTTP which prevents you from data leaks to the public and also from falling for phishing.
Why do we need SSL certificates to let the browser know the connection is secure?
First, while you’ll find many people still talking of “SSL”, today we’re using “TLS” as the encryption method when we send information via HTTPS. “SSL” is an old method that shouldn’t be used anymore. HTTPS in general works with certificates, which you can get from your hosting company, to create a secure, encrypted channel in the HTTP protocol to send data. To encrypt the data you need a private key and a public key.
To make this work, you need a so called “X.509”-certificate on your server that contains the information about the site’s authenticity, approved by a root certificate authority (Let’s Encrypt, StartSSL, or similar).
All browsers, on the other hand, have a set of known and trusted root certificate authorities built-in. This is done for a more convenient user experience — the user does not need to review the certificate and approve it to establish the connection to the site. At some point you have probably seen a popup by the browser asking you if you want to trust the website connection because it’s using an unknown identity. This happens when the certificate has not been created by an official, trusted authority. Of course, there are many complex points I’m glossing over here so make sure to read more detailed resources if you’re interested in getting more information to a specific feature or technology (we link a few on the bottom of this article).
A browser needs these certificates to verify if the keys match, this ensures that neither the server, client, or anything in between has been intercepted and (accidentally or otherwise) leaked your precious data. That sounds pretty secure, but there a couple of issues in the details that could still allow attackers to intercept the connection between the client and the server. HTTPS is no magic bullet, but it does make getting at your information a lot more difficult.
As your article states, I was also under the naïve assumption that all I had to do was redirect my site to
https in my server configuration file and then tell Cloudflare to switch to HTTPS. Can you describe why this is not the case?
This is not entirely wrong. So, with a service like Cloudflare things are a bit more complex. They offer a bunch of services, for example: DNS hosting, performance optimization, and security enhancements. But a lot of people sign up for Cloudflare because they provide “free SSL”. This indeed is a great feature which totally makes sense as you want to serve all your content over HTTPS, so your CDN should support HTTPS as well.
Unfortunately, and that is what most people don’t understand, they can only provide this for their part of the connection. This means that they start using HTTPS on their servers and then serve content from there to the client. If your website (the so called origin host) does not support HTTPS, this means the data is completely unprotected between your origin and Cloudflare. Even worse, this gives the user the impression that the site and data entered on the site is encrypted and protected while in fact it’s not. Cloudflare cannot modify settings on your server, so they can only do their part to make things safer. You still need to ensure that you’re providing security for the data on your origin server. That‘s what most people fail to understand.
If you did the first thing right — enabled HTTPS on your origin server — then things are slightly better. In this case, you can tell Cloudflare to only connect to your origin over HTTPS and to only serve content to the client using HTTPS. Now we have one more problem: Cloudflare’s Full SSL does not validate the origin certificate – it just uses it, so it might be invalid, self-signed, malicious. At least it means the connection between the servers is always secured by HTTPS. There is what Cloudflare calls “Full SSL strict” which validates the certificate itself, but it's more like “Basic SSL” because you can’t ensure your customer’s data is encrypted and safe.
Cloudflare (or any other third party service) sits between browser and server and optimizes (i.e. modifies) content for delivery, or to prevent attacks on your server. The problem is that the data is unencrypted while it's at Cloudflare. HTTPS works for the transfer but is not end-to-end encryption of the actual data sent. This means all content temporarily is unencrypted on the third party service’s machine. Even if you fully trust the company itself with your (and your client’s) data, then the problem is that another third party could gain access to such traffic-optimizing servers and read data or modify it, resulting in either the origin or the client getting modified content.
If you can, you should additionally enable HSTS, or HTTP Strict Transport Security. You do this by adding a rule to your server config that sets this flag. If you set this flag, a browser will only connect to the specified domain over HTTPS for the given timeframe. The timeframe should be set very long, Twitter for example sets it to 20 years to avoid this rule being changed in the event of an attack on their servers. You can also opt-in to include subdomains in this rule.
Finally, to prevent your site being exploited due to a compromised root certificate authority, you can set up HPKP, or HTTP Public Key Pinning, which fills the last gap on security for HTTPS. Unfortunately, if you do something wrong here, the consequences are really bad and could mean your website is not available anymore for the timeframe you’ve set (which shouldn’t be too short). You can read more on that matter and how to set HPKP up in this great article by Scott Helme.
Let's Encrypt seems like a big step in the right direction in terms of generating certificates but this still requires knowledge of the command line. Why is basic web security so complex? Why are there not simpler solutions to these problems?
Oh yes, it’s great to finally see progress on this with Let’s Encrypt. HTTPS has been around since 1994 and so I’m quite happy that finally, people are beginning to work towards simplifying the process of setting up HTTPS. I see Let’s Encrypt only as the beginning.
Talking about this specific service. It’s just reached public beta status. Currently, it only works on the CLI and is very limited when it comes to being run without root privileges. So although it’s great to see things getting simpler, there are still too many hurdles to overcome.
I’m eagerly awaiting the point where all hosting companies begin to offer HTTPS for free with a super-easy and automated setup process of for any given domain. Because, honestly, today setting up HTTPS properly is way too complex, even for tech-savvy people.
Who do you think should be responsible for web security? Should front-end developers spend more time learning about this stuff? Or is the onus on hosting companies to figure out a more elegant technical solution to the problem — like not offering HTTP access at all?
This is a complex question that can’t be solved that easily. In an ideal world, setting up HTTPS properly for a domain would be easy as a click in a web host’s interface or a single command on a server for a server admin. There’s still a long way to go until we reach that point. Until this is the case, us developers need to take care of this.
As a full-stack or backend developer, you should take care of setting up the certificate on the server. As a front-end or full-stack developer you should take care to enable HSTS and enforcing HTTPS by default, taking care of a proper Content Security Policy, along with other security measures. Each developer, regardless of their title, has a duty to ensure the built project creates a safe and encrypted environment for its users.
Regarding not offering HTTP at all anymore—let’s talk about this again when we solved the still-remaining problems described above. Until then, I don’t believe we should aim to “deprecate” HTTP in general, especially as we still have a lot of legacy regarding hardware, cipher-support, and software out there in the world which would need to go away for a HTTPS-only world.
Which resources would you recommend so that I can learn more about web security?
Fortunately, these topics are well covered with lots of helpful blog posts out there. In general, you should read the articles written by Scott Helme to get into details of specific security features and how to enable them on your website. He has also built securityheaders.io, a tool that checks your site on how secure it is and what you should improve.
Finally, if you want to know more, check this security link list by Troy Hunt. And if you want to get an overview of the basic technologies then you can find good explanations on Wikipedia as well.