The Internet is a free and open platform to share knowledge and information. Over the years, organisations with less good and honest intentions abused the free and open character of the Internet to attack its users. This for money, data and many other purposes.
You can improve internet security in a lot of ways if you understand how the internet works. In this article, we dive into the what and why of HTTP Security Headers. We also present an overview of commonly used headers and explain how you can implement them in your WordPress website.
HTTP Security Headers
In general, HTTP headers are used to send extra parameters (settings, security, keys, ...). The receiver is the browser or the server. The values of the HTTP headers are used to influence the response. For example, if you set the right HTTP Security header, you can force encryption for your website. One example is the "Date" header where the value is the current timestamp. For a full list of HTTP headers, see the dedicated page "List of HTTP header fields".
Using HTTPS Security Headers, you can instruct web browsers how to behave in certain situations. In the response, generated on the server, multiple security headers can be added.
Before guiding you through some common security headers, let's take a look at a tool to test your headers. The website https://securityheaders.com can help you!
Once you enter your domain, it will send a request to your website and grade it, based on set headers. For this article, I disabled all headers on this website which resulted in a big red F.
Now, let's change this F to a nice A!
Which security headers?
We will focus on 6 headers that are considered essential by securityheaders.com. In total, there are 10 available security headers.
- HTTP Strict Transport Security (HSTS)
HTTP Strict Transport Security (HSTS)
Web browsers are stimulating website owners to add an SSL-certificate to their hosting, so all traffic is encrypted. This is visualised with a green padlock in the address bar and all major
browsers try to make their users aware of the risks when there is no padlock. So, once your SSL-certificate is installed, you might think everything is secure. This is true unless someone makes your visitor browse to the non-SSL version of your website. sslstrip is a variant of the Man in the Middle attack where the SSL encryption is stripped from your connection by redirecting the browser to the non-SSL version.
When adding the HSTS header, your browser will get the instruction to only use the SSL-secured version of your website. Your browser will never try to access the unencrypted version of your website again. Not until the header expires.
The X-Frame-Options header is a countermeasure for Clickjacking attacks. In a Clickjacking, the attacker tricks the visitor into clicking a button that performs a hidden action, without the user knowing what's happening.
For example, the visitor clicks a 'play' button, while in the background the click initiates a purchase on Amazon. The hacker assumes the visitor is logged-in to Amazon and has 1-click ordering enabled. The chances of success with this tactic are very small, but when you generate enough traffic on your website, you increase the effectiveness of the attack.
By defining the X-Frame-Options header, you limit the possibilities of putting your website in an iframe.
There are 3 possible modes:
- DENY - No one is allowed to put this website in an iframe
- SAMEORIGIN - The iframe can only be located on the same domain
- ALLOW-FROM - You can specify which domains can put the website in an iframe
XSS stands for Cross-site scripting and uses vulnerable web-applications or websites to serve frontend scripting code. This code will typically send form inputs to another domain. Common data are login credentials, contact forms, checkout data, ... Attackers use the data they obtained during the attack.
An example of an XSS-attack:
Website owners can protect their web-application or website by setting the X-XSS-Protection header.
There are 3 possible modes:
- 0 - Turns it off
- 1 - Removes (filters out) scripts that are generated by the request, but will still render the webpage
- 1; mode=block - If a script is detected, the webpage will be blocked from being rendered
All information on the MDN website can be found here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
In the beginning, the world wide web was not that organised, and many servers didn't send the header that defines which type of content is being sent to the visitor. To give visitors a better browsing experience, browsers started guessing how to interpret the source code. For example, an image with hidden scripts will be served as an image, and, additionally, the hidden script will be executed if you don't send the appropriate header. This is called "Content sniffing". Browsers will show an image when the data looks like an image, but you can hide malicious code in the source of an image. Since the browser guesses its an image, you will see the image and won't be aware of the code.
On your server, you can tell the browser not to guess and show the content as defined from the server. Most browsers support the X-Content-Type-Options header.
When a visitor clicks a link, automatically a "Referer" header is added, which tells the server where the visitor is coming from. This header is used for analytical purposes.
As you understand, this poses a privacy problem. Any visitor can be tracked without him/her know so. Do your visitor a favour and set this header.
There are many possible modes for this header:
- (empty string) - No policy is set. All referrers will be sent
- no-referrer - No referrers, never
- no-referrer-when-downgrade - No referrer when downgrading security (link to http)
- same-origin - No referrer when security is different (http to https) or when on a different domain
- origin - Only main domain is sent, no path
- strict-origin - Only the main domain is sent, no path AND when security is in place
- origin-when-cross-origin - Full path when on the same domain, domain only when cross-domain
- strict-origin-when-cross-origin - Full path when on the same domain, domain only when cross-domain AND when security is in place
- unsafe-url - All referrers will be sent
All information on the MDN website can be found here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
A browser has so many built-in features nowadays, it's easy for attackers to use them to invade a visitors' privacy. For example, by tracking the visitors' behaviour or by recording sound/video, tracking location, ... Using the Feature-Policy header, you as a website owner can limit the available browser features for a website. You can also do the same for all embedded websites.
The biggest difference between the Feature-Policy and other Security Headers is a large number of options. For every feature, you should define what's possible and what not.
Below are all the features that are known at the moment:
All of these features have the following modes available:
- * - Website and all embedded frames can use the feature
- self - Website and embedded sites on the same domain can use the feature. No external embeds
- none - The feature will be disabled for the current page and all embedded sites
- <origin(s)> - Only specific domains can use this feature
You will notice this needs a certain amount of configuration, but once it is set up, it adds a considerable amount of extra security for visitors of your website.
Setting this up in your WordPress
How do we implement the HTTP Security Headers in a WordPress website?
It isn't possible to set Security Headers in your wp-config or in the wp-admin, so, we need to look at the plugin repository instead. When searching through the plugin repository, you will only find a very limited list of possible plugins. For this post, we choose the "HTTP-headers" plugin. The interface in wp-admin is simple and clean.
On the HTTP Headers dashboard, there are 6 categories of available options. Right now our only focus is on the first: Security.
Set HTTP Security Headers
We explained the use of the most common headers earlier. Below, we will show the settings which we use for our websites.
- Mode: SAMEORIGIN
- Mode: 1; mode=block
- Mode: nosniff
- max-age: 1 year
- includeSubDomains: checked
- preload: checked
- Mode: strict-origin-when-cross-origin
This is the most complex HTTP Security Header we've set in this blogpost, since you have to find out which features are used on your website.
Which mode is used to send headers?
While researching for this post, we've set the headers through the .htaccess file, however, a few errors occurred. In cooperation with our hosting partner, we figured out that enabling mod_fcgid and mod_headers might cause conflicts. This results in not sending headers. The solution that fixed it for our websites, is to use PHP to send headers, although this is a deprecated feature.
You might want to check this with your hosting partner.
Once you've set up the HTTP Security Headers and you re-scan your website, you'll get a nice grade A for this.
HTTP Headers are not too hard to set up and add an extra layer of security for your visitors. So basically it's a no-brainer to do this.
Don't hesitate to contact us if you have any questions.