Module 4 · 4.2
English
Your website: https, HSTS and security headers
Module 4: Email, website and domain · Reading time: 11 minutes
Learning objective: After this lesson you can check your website's basic security: a valid certificate, redirecting to https, HSTS with a sensible max-age, the most important security headers and keeping your CMS up to date.
Key concepts: TLS certificate, https, redirect to https, HSTS, max-age, includeSubDomains, preload, HTTP header, Content-Security-Policy, X-Content-Type-Options, frame-ancestors, X-Frame-Options, Referrer-Policy
What happens when someone opens your site
When a customer types example.com into the address bar, the browser requests the page from your web server. That conversation runs over HTTP. With https, there's an encrypted connection wrapped around it: TLS. For that, your website needs a TLS certificate (often still called an SSL certificate). The certificate proves that the server really belongs to example.com, and the encryption makes sure nobody along the way can read or change anything. That matters on public wifi, where you don't know who manages the network (lesson 5.3).
With every response, the server sends along a set of headers in addition to the page itself: short lines with information and instructions for the browser. You don't see them on screen, but they largely determine how safely the browser handles your site. Some of these headers are security headers. In this lesson we'll go through the four layers: certificate, redirect, HSTS and headers. After that, we'll briefly look at keeping your website itself up to date.
Layer 1: a valid certificate
A certificate is fine if it meets three conditions:
- it has not expired;
- it was issued by a trusted issuer (a certificate authority that browsers recognise, such as Let's Encrypt or a commercial provider);
- it's valid for exactly the name the visitor opens:
example.comandwww.example.comif you use both.
Nearly every hosting provider nowadays arranges a free certificate that renews itself automatically. If something goes wrong, it's usually because the domain name points to a different server, or because a CAA record blocks the issuer (lesson 4.3).
Important to know: a padlock says nothing about how trustworthy a site is. It only says that the connection is encrypted and that the certificate matches the name in the address bar. Phishing sites on mijnbank-veilig.example have a padlock too. That's why you learn to read domains in lesson 3.2.
Layer 2: always redirect to https
A certificate alone isn't enough. Anyone who opens http://example.com, for example via an old link or by just typing the name, should automatically land on the https version. This is called a redirect (usually with status code 301).
A sensible order is:
http://example.com -> https://example.com
https://example.com -> https://www.example.com (only if you use www as the main address)
http://www.example.com -> https://www.example.comNote the first line: redirect from http to https on the same name first, and only afterwards, if needed, to www. That way the browser can also receive the HSTS instruction for the bare name. Internet.nl checks exactly this.
A common mistake is double redirecting: in the hosting panel and in a plugin or in .htaccess. That can create an endless loop ("too many redirects"). Use one place only.
Layer 3: HSTS
Redirecting has a weak moment: the very first request still travels unencrypted over http. An attacker on the same network can intercept that one request and keep the visitor on a fake, unencrypted version. That's what HSTS (HTTP Strict Transport Security, RFC 6797) is for.
With HSTS, your site sends a header along over https:
Strict-Transport-Security: max-age=31536000; includeSubDomainsThe browser then remembers: "open this site only via https, for the next 31,536,000 seconds (a year)". If the visitor later types http://example.com, the browser converts it to https itself, before anything even travels over the network. The weak first request disappears.
| Part | Meaning |
|---|---|
max-age= | How long the browser remembers it, in seconds. Internet.nl considers at least a year (max-age=31536000) sufficient; a short period doesn't protect people who only visit your site occasionally. |
includeSubDomains | Also applies to all subdomains, such as shop.example.com and mail.example.com. |
preload | You're requesting inclusion in the list built into browsers (hstspreload.org). Then even the very first visit is protected. Requirements include: a max-age of at least a year, includeSubDomains, and all subdomains on https. Getting removed again takes a long time. |
max-age=0 | Clears the remembered instruction. |
Three things you need to know before turning on HSTS:
- https must work everywhere first. A browser that has remembered HSTS and encounters a certificate error gives the visitor no button to continue anyway (RFC 6797, section 12.1). If your certificate expires or doesn't match for
www, your site becomes unreachable for those visitors until it's fixed. includeSubDomainsaffects everything under your domain. An old subdomain without a certificate, for example a printer or camera page oncamera.example.com, can no longer be opened afterwards.- Build it up gradually. Start with a short
max-age(for example one day), check that everything works, and increase it step by step to a year. Wait out the full period at each step.
The browser ignores an HSTS header that arrives over plain http. So you'll only see it in the https response.
Layer 4: security headers
Besides HSTS, there are a few headers that tell the browser what it may and may not do with your pages. You don't need to get all of them perfect, but the first three are simple and risk-free.
| Header | Against what | Good value |
|---|---|---|
X-Content-Type-Options | The browser starts guessing what a file is, which means an uploaded "image" could be executed as a script. | nosniff (the only valid value) |
Content-Security-Policy: frame-ancestors ... or X-Frame-Options | Clickjacking: another site loads your page invisibly in a frame and tricks visitors into clicking your buttons without realising. | frame-ancestors 'self' or 'none'; the older header X-Frame-Options: SAMEORIGIN or DENY |
Referrer-Policy | When someone clicks through to another site, the browser sends along the address of the previous page. That can contain sensitive information, such as a search term or an order number. | no-referrer or same-origin (strict), strict-origin-when-cross-origin (common; internet.nl gives a warning here) |
Content-Security-Policy (full) | Restricts where scripts, styles and images may load from. Makes injected malicious scripts (XSS) much harder. | Custom per site. Avoid unsafe-inline, unsafe-eval and wildcards. |
A full Content-Security-Policy is the most powerful option, but also the trickiest: a rule that's too strict can break your statistics, your payment button or your chat window. With the Content-Security-Policy-Report-Only variant you can first measure what would be blocked, without breaking anything. Leave this to your web developer, or start with just frame-ancestors.
Checking headers yourself
Open your site in a browser, press F12 (or choose "Inspect"), go to the Network tab, reload the page and click on the first request. Under "Response Headers" you'll see everything the server sends along. You can also do it from the command line:
curl -sI https://example.com/The website itself: CMS, plugins and themes
The best headers won't help if the software behind your site is vulnerable. Most hacked small business sites weren't breached through the web server, but through an outdated plugin, a theme that hasn't been updated in years, or a weak admin password.
- Turn on automatic updates for your CMS (for example WordPress, Joomla or another system) and for plugins wherever possible.
- Remove plugins and themes you don't use; disabling isn't enough, the files are still there.
- Use a strong, unique password and two-factor authentication for the admin login (module 2), and limit the number of login attempts.
- Keep the PHP version (or other language) of your package on a version that still receives updates (lesson 5.1).
In practice: what it looks like
In DirectAdmin, the panel WebOké uses, you first turn on Secure SSL for your domain, and then Force SSL with https redirect. In the same place there's a switch for HSTS; only turn that on once the certificate works for all names. With other providers it works similarly, or you arrange it in your CMS settings.
If your site runs on Apache or LiteSpeed, you can also set the headers in .htaccess:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000"
Header always set X-Content-Type-Options "nosniff"
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>Only add includeSubDomains once you're sure every subdomain has https. After every change, check with internet.nl's website test or with your browser's developer tools.
Summary
- A padlock means: encrypted and the right name. It does not mean: trustworthy.
- Always redirect http to https, first on the same name, and in one place only.
- HSTS lets the browser remember that your site only goes via https; internet.nl considers a
max-ageof at least a year (31536000) good. Only turn it on once https works everywhere, and build it up gradually. X-Content-Type-Options: nosniff,frame-ancestors(orX-Frame-Options) andReferrer-Policyare simple; a full Content-Security-Policy is custom work.- Updates to your CMS, plugins and themes matter at least as much as headers.
Quiz
Exercise
Exercise A4.2: Checking the protection of your domain. Enter your website's domain name (if you don't have one, use internet.nl). The program opens http:// and https:// for your domain and checks the certificate, the redirect to https, HSTS and the security headers. You'll get green, orange or red for each point, with an explanation.
Exercise D4.2: Updating and tidying up your website. Log in to your website's admin area, check the version of your CMS, plugins and themes, remove what you don't use, and turn on automatic updates wherever possible. Tick off the checklist and answer the reflection question.
Exercise D4.2: Updating and tidying up your website
How to tackle it: (1) Log in to your website's admin area (or ask your web developer to do this together with you). (2) Note down your CMS version and check whether updates are available. (3) Make a backup (lesson 6.1), then install the updates for your CMS, plugins and themes. (4) Remove plugins and themes you don't use. (5) Turn on automatic updates where possible. (6) Check which admin accounts exist and remove accounts of people who no longer work there. (7) Turn on two-factor authentication for every admin account.
Your ticks and notes only stay in this browser; we don't send them anywhere. If you're signed in, we only save in My courses that you've done the exercise.
Further reading
The steps in the WebOké articles apply to the WebOké environment; with other providers it works similarly.
- Activating, renewing, and troubleshooting SSL certificates
- Force redirect visitors to https
- DirectAdmin guide 6.4: Always redirect visitors to https
- DirectAdmin guide 6.7: No padlock or 'not secure': fixing mixed content
- DirectAdmin guide 15.10: Web Application Firewall
- Securing wp-login.php in WordPress
- Internet.nl, website test (independent): https://internet.nl
- RFC 6797, HTTP Strict Transport Security: https://www.rfc-editor.org/rfc/rfc6797
- HSTS preload list: https://hstspreload.org
- MDN, explanation of the headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security
