When it comes to securing your website, it’s all about minimizing attack surface and adding more layers of security. One strong layer that you can (and should) add is proper HTTP security headers. When responding to requests, your server should include security headers that help stop unwanted activity like XSS, MITM, and click-jacking attacks. While sending security headers does not guarantee 100% defense against all such attacks, it does help modern browsers keep things secure. So in this tutorial, we walk through seven of the most important and effective HTTP security headers to add a strong layer of security to your Apache-powered website.
Contents
X-XSS-Protection
X-Frame-Options
X-Content-Type-Options
HTTP Strict Transport Security (HSTS)
Referrer-Policy
Feature-Policy
Content-Security-Policy
All Together
Note: You can verify your site's security headers using a free online tool such as the one provided by SecurityHeaders.com.
X-XSS-Protection
The X-XSS-Protection
security header enables the XSS filter provided by modern web browsers (IE8+, Chrome, Firefox, Safari, et al). Here is the recommended configuration for this header:
# X-XSS-Protection
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to block any requests containing malicious scripts. For more configuration options and further information about X-XSS-Protection
, check out these resources:
- MDN Docs: X-XSS-Protection
- X-XSS-Protection – Preventing Cross-Site Scripting Attacks
- Increase Security with X-Security Headers
X-Frame-Options
The X-Frame-Options
(XFO) security header helps modern web browsers protect your visitors against clickjacking and other threats. Here is the recommended configuration for this header:
# X-Frame-Options
<IfModule mod_headers.c>
Header set X-Frame-Options "SAMEORIGIN"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to block any frames/content requested from external locations. So if your own site includes an iframe that loads a resources from the same domain, the content will load normally. But if any iframe is included that loads resources from any other domain, the content will be blocked. For more configuration options and further information about X-Frame-Options
, check out these resources:
- MDN Docs: X-Frame-Options
- X-Frame-Options – How to Combat Clickjacking
- Increase Security with X-Security Headers
X-Content-Type-Options
The X-Content-Type-Options
security header enables supportive browsers to protect against MIME-type sniffing exploits. It does this by disabling the browser’s MIME sniffing feature, and forcing it to recognize the MIME type sent by the server. This header is very flexible and may be configured extensively, however the most common implementation looks like this:
# X-Content-Type-Options
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to use the MIME type declared by the origin server. There are a couple of precautions to keep in mind. First, as with any security header, it does not stop 100% of all attacks or threats; it does stop some of them, however, and thus provides another layer of protection for your site. Also note that this header currently is supported only in Chrome and later versions of Internet Explorer. Hopefully other browsers will add support in the future. For more configuration options and further information about X-Content-Type-Options
, check out these resources:
- MDN Docs: X-Content-Type-Options
- X-Content-Type-Options HTTP Header
- Increase Security with X-Security Headers
Strict-Transport-Security
The Strict-Transport-Security
(HSTS) header instructs modern browsers to always connect via HTTPS (secure connection via SSL/TLS), and never connect via insecure HTTP (non-SSL) protocol. While there are variations to how this header is configured, the most common implementation looks like this:
# Strict-Transport-Security
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to always use HTTPS for connections. This helps stop man-in-the-middle (MITM) and other attacks targeting insecure HTTP connections. For more configuration options and further information about Strict-Transport-Security
, check out these resources:
Referrer-Policy
The Referrer-Policy
security header instructs modern browsers how to handle or exclude the Referer
header (yes the header normally is spelled incorrectly, missing an “r”). For those who may not be familiar, the Referer
header contains information about where a request is coming from. So for example if you are at example.com
and click a link from there to domain.tld
, the Referer
header would specify example.com
as the “referring” URL.
With that in mind, the Referrer-Policy
enables you to control whether or not the Referer
header is included with the request. Here is an example showing how to add the Referrer-Policy
header via Apache:
# Referrer-Policy
<IfModule mod_headers.c>
Header set Referrer-Policy "same-origin"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to only set the referrer header for request from the current domain (same-origin
). Keep in mind that this header is less about security and more about controlling referrer information, as is required by various rules and regulations (e.g., GDPR). For more configuration options and further information about Referrer-Policy
, check out these resources:
Feature-Policy
The Feature-Policy
header tells modern browsers which browser features are allowed. For example, if you want to ensure that only geolocation and vibrate features are allowed, you can configure the Feature-Policy
header accordingly. It also enables you to control the origin for each specified feature. Here is an example showing how to add a Feature-Policy
header via Apache:
# Feature-Policy
<IfModule mod_headers.c>
Header set Feature-Policy "geolocation 'self'; vibrate 'none'"
</IfModule>
Added to your site’s .htaccess
file or server configuration file, this code instructs supportive browsers to enable only geo-location and vibrate features. Keep in mind that this header is less about security and more about ensuring a smooth experience for your users. For more configuration options and further information about Feature-Policy
, check out these resources:
- MDN Docs: Feature-Policy
- A new security header: Feature Policy
- Google Docs: Introduction to Feature Policy
Content-Security-Policy
The Content-Security-Policy
(CSP) header tells modern browsers which dynamic resources are allowed to load. This header is especially helpful at stopping XSS attacks and other malicious activity. This header provides extensive configuration options, which will need to be fine-tuned to match the specific resources required by your site. Otherwise if the header configuration does not match your site’s requirements, some resources may not load (or work) properly.
Because of this, there isn’t one most common example to look at. So instead here are a few different examples, each allowing different types of resources.
Example 1
First example, here is a CSP directive that allows resources from a CDN, and disallows any framed content or media plugins. This example is from the Google docs page linked below.
# Content-Security-Policy - Example 1
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src https://cdn.example.com; child-src 'none'; object-src 'none'"
</IfModule>
Example 2
Second example, this CSP directive enables script resources loaded from a jQuery subdomain, and limits stylesheets and images to the current domain (self
). This example is from the Mozilla docs page linked below.
# Content-Security-Policy - Example 2
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'none'; img-src 'self'; script-src 'self' https://code.jquery.com; style-src 'self'"
</IfModule>
Example 3
And for a third example, here is the directive I use on most of my WordPress-powered sites. Logically these sites tend to use the same types of resources, so I can keep things simple and use the following code on all sites:
# Content-Security-Policy - Example 3
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src https:; font-src https: data:; img-src https: data:; script-src https:; style-src https:;"
</IfModule>
To get a better idea of what’s happening here, let’s apply a bit of formatting to the code:
Header set Content-Security-Policy "
default-src https:;
font-src https: data:;
img-src https: data:;
script-src https:;
style-src https:;
"
Stare at that for a few moments and you should get the idea: the header is setting the allowed source(s) for fonts, images, scripts, and styles. For each of these, a secure HTTPS connection is required. The only exception is also to allow data
URIs as a source for fonts and images.
So for any of these examples, when added to your site’s .htaccess
file or server configuration file, the code tells supportive browsers which dynamic resources are allowed and/or not allowed. But seriously, if you’re thinking about adding the powerful Content-Security-Policy
security header, take a few moments to read thru some of the documentation:
- MDN Docs: Content Security Policy
- MDN Docs: Implementing Content Security Policy
- Google Docs: Content Security Policy
- Content Security Policy Reference
Where to get help with CSP
Yes CSP can be confusing, but there is no reason to despair. There are numerous online tools that make it easier to figure out how to implement CSP, for example here are some top sites:
A quick search for “csp test online” yields many results.
Even better, they now have “CSP generators” that literally write the code for you based on your input variables. Here are two solid looking CSP generators:
There are lots of useful tools out there to make CSP easier. Just enter your infos and copy/paste the results. If in doubt, use multiple tools and compare the results; the code should be the same. If not, don’t hesitate to reach out to the tool providers, who will be able to answer any questions, etc.
All Together
For the sake of easy copy/pasting, here is a code snippet that combines all of the above-described security headers.
Important: before adding this code to your site, make sure to read through each technique as explained in corresponding sections above. There may be important notes and information that you need to understand regarding each particular directive included in this code snippet.
# Security Headers
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
# Header set Content-Security-Policy ...
Header set Referrer-Policy "same-origin"
Header set Feature-Policy "geolocation 'self'; vibrate 'none'"
</IfModule>
As with each of the above techniques, this code may be added to your site via .htaccess or Apache config. Understand that this technique includes commonly used configurations for each of the included headers. You can (and should) go through each one to make sure that the configuration matches the requirements and goals of your site. Also remember to test thoroughly before going live.
Note: Notice the following line in the above “Security Headers” code snippet:
# Header set Content-Security-Policy ...
The pound sign or hash tag or whatever you want to call it means that the line is disabled and is ignored by the server. This means that the Content-Security-Policy
directive is “commented out” and thus not active in this technique. Why? Because as explained previously, there is no recommended “one-size-fits-all” CSP example that works perfectly in all websites. Instead, you will need to replace the commented out line with your own properly configured CSP header, as explained above.
Leave a Reply