Apache Security headers are a method to incorporate some security settings into websites to reduce the risk of various hacking attacks. The following sections provide some of the more common headers that should be set.
One proviso with all of these settings is that we assume the end-users browser is relatively current and recognises or honours the header setting instructions. Likewise you should be using a current Apache server release.
The same (similar) headers can also be used with nginx but that is beyond the scope of this article.
The first option to set is turning off the details of the server operating system.
ServerSignature Off ServerTokens Prod
The reason for doing this is to hide information relating to the server from potential hackers. Advertising your servers operating system and version release allows them to look at specific vulnerabilities that might exist.
Clarification with this. There is no option to show the Server as ‘blank’ in the selection process. The combination above will still show as Apache, but will not include versioning details etc.
Also note that if you are using a CPanel server, you already have these options in the settings at WHM(Home) -> Service Configuration -> Apache Configuration -> Global Configuration.
The set-cookies header is important as one of the main cross-site-scripting attacks are looking for session cookies that are used by many websites to manage the site user connections.
Header always edit Set-Cookie (.*) "$1;HttpOnly;Secure;SameSite=Strict"
The HttpOnly may seem a little off in this day of Https:// everywhere, but that is the purpose of the Secure setting. In detail:
- $1; is the original cookie, which Apache will edit to append these 3 settings:
- HttpOnly; specifies that the cookie cannot be read through a client browser
- Secure; adds the ‘s’ to http: and safely encrypts the cookie
- SameSite=Strict; Cookies will not be sent in 3rd party requests, i.e. only used within the same site.
All that said, I am still having issues getting this recognised on a CPanel server. Time to ask the audience!
Read more on this at https://owasp.org/www-community/HttpOnly.
Managing MIME-types, like text/html, in the website pages should be accepted as configured by the website. The purpose is to block content ‘sniffing’ that may provide a method for a hacker to execute some code that should not be executed on the site.
Header set X-Content-Type-Options nosniff
For more details check out Mozilla Developer MDN document for X-Content-Type-Options.
The X-Frame-Options setting is to manage the use of iframes to embed site content into another site. The goal is to prevent what is commonly known as click-jacking, where a foreign website can embed your website within an iframe. This means the foreign site can look like your site but have additional, and probably malicious code running in the background.
Header set X-Frame-Options: "SAMEORIGIN"
Setting “SAMEORIGIN” says to only allow iframes to be used within the site and not from any external location. For more details check out Mozilla Developer MDN document for X-Frame-Options.
Strict-Transport-Security or HSTS
This header relates to having a SSL secure certificate for your website, i.e. using https:// rather than plain http:// to access the site. The max-age is effectively the time-to-live for the setting before it will be checked again. In the example
2592000 is one month. Longer max-age settings are recommended for use with the preload option. Try 31536000 for one year.
Header always set Strict-Transport-Security "max-age=2592000; includeSubDomains; preload"
The ‘preload’ is not an official setting but is commonly accepted. There are conditions to using the preload option. For more details check out Mozilla Developer MDN document for Strict-Transport-Security. I tend to leave preload out at this time as it entails some obligations that will consume more time.
Adding Apache security headers to a WHM / Cpanel server for all client sites is something that should be done by the server administrator. If you are a CPanel account holder and your site fails the header report you should hit-up your web host for an explanation or find a host that has these things configured already.
All in one block, (in no particular order) your security headers could look like this:
# Global Security Headers <IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains;" Header always edit Set-Cookie (.*) "$1;HttpOnly;Secure" Header always set X-Frame-Options "sameorigin" Header setifempty Referrer-Policy: same-origin Header set X-XSS-Protection "1; mode=block" Header set X-Permitted-Cross-Domain-Policies "none" Header set Referrer-Policy "no-referrer" Header set X-Content-Type-Options: nosniff Header set Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()" #Header set Content-Security-Policy: "default-src *" </IfModule>
Using the above, with the Content-Security-Policy enabled, the free script tool over at https://securityheaders.com will show a nice big A+ and lots of green ticks. Noting that it is not checking the Set-Cookie option.
Content-Security-Policy is a more comprehensive header and supercedes some of the headers described here. Lots more work to be done with this setting as it is targetting individual sites rather than shared hosting servers. If its enabled the setting above actually does nothing other than get a green tick in the security report at https://securityheaders.com. It also breaks many WordPress sites as while the default-src is the ‘fall-back’ position for most of the ‘-src’ options in CSP, in-line scripts are governed by the script-src parameter and it does not accept ‘*’ as a value, so the ‘fall-back’ breaks and browsers will not load the site with errors like:
As a result I have commented that line out for my servers today while I look at this in more detail.
The joys of new protocols!