“There is no such thing as perfect security, only varying levels of insecurity.” – Salman Rushdie
A multi-part series by John Ball, Phillip Kuzma, and Ted Nass on web server security.
In a hurry? Click here for the step-by-step instructions.
Security headers are part of HTTP header responses from servers to browsers that request website content. Wikipedia defines HTTP headers as:
“HTTP header fields are components of the header section of request and response messages in the Hypertext Transfer Protocol (HTTP). They define the operating parameters of an HTTP transaction.”
Security headers (HTTPS Headers, HTTP Secure Headers) give specific instructions to browsers on how to load content from websites and are an easy-to-implement solution for mitigating known vulnerabilities in HTTP requests. Plus, if implemented correctly, you’ll get good marks on your security reports. 😉
https://SecurityHeaders.io is a great website/tool for scanning your server to determine what security headers are available or presented when a browser requests a connection to your web server and the status of each header option.
For example, the SecurityHeaders.io site ranks https://www.johndball.com with an “A+” as of this posting.More details can be seen here: https://securityheaders.io/?q=https%3A%2F%2Fwww.johndball.com%2F
For this particular site, some of the headers I set on the server back-end and using the Cloudflare front end. Others I set directly in WordPress using the “WP Content Security Policy Plugin“. In an ideal environment, these settings would be set server-side in the native server application and on the Cloudflare front end but a balance between ease of implementation and management was found (for me) using these options. A breakdown of the settings for this particular site (with clickable links for more info) are:
- HSTS – Set Server Side – Set Front End Side
- X-Frame-Options – Set Server Side
- Content Security Policy – Set Server Side w/Plugin
- X-Content-Type-Options – Set Server Side
- X-XSS-Protection – Set Server Side w/Plugin
- Referrer-Policy – Set Server Side w/Plugin
- Expect-CT – Server Side w/Plugin – Set Front End Side
As you can see, I tried to at least enable every option server-side using Apache options, then layered on Cloudflare protection, and as a stop-gap used a plugin to fill in the gaps.
- Download and install the WP Content Security Policy plugin. It can be found here: https://wordpress.org/plugins/wp-content-security-policy/
- Navigate to “Settings” –> “CSP Options“. Ensure you save changes on each tab once set according to your needs.
- Under the “CSP Control” tab we want to set:
- Under the “Content Security Policies” tab we want to set:
- Under the “Headers” tab we want to set:
- Mode: Enforce Expect CT
- Maximum Age: One Hour (3600 seconds)
- Mode: DENY (unless you set x-frame/i-frame options in All In One WordPress Security then ignore this setting)
- Mode: 1; mode=block – Enable Filtering, block invalid requests
- Mode: nosniff
- Under the “CSP V3” tab, read the caveat and, if comfortable with the warnings, click “Convert script-src to CSP V3” then save changes.
- Head over to the “Test” tab and click “Internal Test URL Checker“. You should get a “Finished tests with no issues.” notice at the bottom of the page. If not, adjust your settings as needed.
- Navigate over to the https://securityheaders.com/ website and validate your settings. You should get all greens except for Strict-Transport-Security (which I set via Cloudflare after extensive testing) and Feature-Policy (which I have not had an opportunity to test. I will update this post once I test this feature.)
Feel free to comment any successes, help, or other options you used.