How to Implement Security HTTP Headers to Prevent Vulnerabilities?
Do you know most of the security vulnerabilities can be fixed by implementing necessary headers in the response header?
Security is as essential as content and SEO of your website, and thousands of websites get hacked due to misconfiguration or lack of protection. If you are a website owner or security engineer and looking to protect your website from Clickjacking, code injection, MIME types, XSS, etc. attacks then this guide will help you.
In this article, I will talk about various HTTP Headers to implement in multiple web servers, network edge & CDN providers for better website protection.
Notes:
- You are advised to take a backup of configuration file prior making changes
- Some of the headers may not be supported on all the browsers, so check out the compatibility before the implementation.
- Mod_headers must be enabled in Apache to implement these headers. Ensure the following line uncommented in
httpd.conf
file.
LoadModule headers_module modules/mod_headers.so
Copy
- Post-implementation, you can use secure headers online tool to verify the results.
Using WordPress?: you may want to try using HTTP Headers plugin, which takes care of these headers and a lot more.
Secure HTTP Headers
- X-XSS-Protection
- HTTP Strict Transport Security
- X-Frame-Options
- X-Content-Type-Options
- HTTP Public Key Pinning
- Content Security Policy
- X-Permitted-Cross-Domain-Policies
- Referrer-Policy
- Expect-CT
- Feature-Policy
X-XSS-Protection
X-XSS-Protection header can prevent some level of XSS (cross-site-scripting) attacks, and this is compatible with IE 8+, Chrome, Opera, Safari & Android.
Google, Facebook, Github use this header, and most of the penetration testing consultancy will ask you to implement this.
There are four possible ways you can configure this header.
Parameter Value | Meaning |
0 | XSS filter disabled |
1 | XSS filter enabled and sanitized the page if attack detected |
1;mode=block | XSS filter enabled and prevented rendering the page if attack detected |
1;report=http://example.com/report_URI | XSS filter enabled and reported the violation if attack detected |
Let’s implement 1;mode=block in the following web servers.
Apache HTTP Server
Add the following entry in httpd.conf of your Apache webserver
Header set X-XSS-Protection "1; mode=block"
Restart the apache to verify
Nginx
Add the following in nginx.conf under http block
add_header X-XSS-Protection "1; mode=block";
Nginx restart is needed to get this reflected on your web page response header.
MaxCDN
If you are using MaxCDN, then adding header is easy and on-the-fly.
Go to Edge Rules >> click “New Rule” and select “Add X-XSS-Protection Header” from the drop-down.
![edgerules](https://geekflare.com/wp-content/uploads/2016/10/edgerules.png)
Microsoft IIS
- Open IIS Manager
- Select the Site you need to enable the header for
- Go to “HTTP Response Headers.”
- Click “Add” under actions
- Enter name, value and click Ok
![iis-x-xss-protection](https://geekflare.com/wp-content/uploads/2016/10/iis-x-xss-protection.png)
- Restart IIS to see the results
HTTP Strict Transport Security
HSTS (HTTP Strict Transport Security) header to ensure all communication from a browser is sent over HTTPS (HTTP Secure). This prevents HTTPS click through prompts and redirects HTTP requests to HTTPS.
Before implementing this header, you must ensure all your website page is accessible over HTTPS else they will be blocked.
HSTS header is supported on all the major latest version of a browser like IE, Firefox, Opera, Safari, and Chrome. There are three parameters configuration.
Parameter Value | Meaning |
max-age | Duration (in seconds) to tell a browser that requests are available only over HTTPS. |
includeSubDomains | The configuration is valid for the subdomain as well. |
preload | Use if you would like your domain to be included in the HSTS preload list |
So let’s take an example of having HSTS configured for one year, including preload for domain and sub-domain.
Apache HTTP Server
You can implement HSTS in Apache by adding the following entry in httpd.conf file
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Restart apache to see the results
Nginx
To configure HSTS in Nginx, add the next entry in nginx.conf under server (SSL) directive
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
As usual, you will need to restart Nginx to verify
Cloudflare
If you are using Cloudflare, then you can enable HSTS in just a few clicks.
- Log in to Cloudflare and select the site
- Go to the “Crypto” tab and click “Enable HSTS.”
![cloudflare-hsts-config](https://geekflare.com/wp-content/uploads/2016/10/cloudflare-hsts-config.png)
Select the settings the one you need, and changes will be applied on the fly.
Microsoft IIS
Launch the IIS Manager and add the header by going to “HTTP Response Headers” for the respective site.
![iis-hsts](https://geekflare.com/wp-content/uploads/2016/10/iis-hsts.png)
Restart the site
X-Frame-Options
Use the X-Frame-Options header to prevent Clickjacking vulnerability on your website. By implementing this header, you instruct the browser not to embed your web page in frame/iframe. This has some limitations in browser support, so you got to check before implementing it.
You can configure the following three parameters.
Parameter Value | Meaning |
SAMEORIGIN | Frame/iframe of content is only allowed from the same site origin. |
DENY | Prevent any domain to embed your content using frame/iframe. |
ALLOW-FROM | Allow framing the content only on a particular URI. |
Let’s take a look at how to implement “DENY” so no domain embeds the web page.
Apache
Add the following line in httpd.conf and restart the webserver to verify the results.
Header always append X-Frame-Options DENY
Nginx
Add the following in nginx.conf under server directive/block.
add_header X-Frame-Options “DENY”;
Restart to verify the results
F5 LTM
Create an iRule with the following and associated with the respective virtual server.
when HTTP_RESPONSE { HTTP::header insert "X-FRAME-OPTIONS" "DENY" }
You don’t need to restart anything, changes are reflected in the air.
WordPress
You can get this header implemented through WordPress too. Add the following in a wp-config.php file
header('X-Frame-Options: DENY);
If you are not comfortable editing the file, then you can use a plugin as explained here or mentioned above.
Microsoft IIS
Add the header by going to “HTTP Response Headers” for the respective site.
![iis-x-frame-options](https://geekflare.com/wp-content/uploads/2016/10/iis-x-frame-options.png)
Restart the site to see the results.
X-Content-Type-Options
Prevent MIME types security risk by adding this header to your web page’s HTTP response. Having this header instruct browser to consider files types as defined and disallow content sniffing. There is only one parameter you got to add “nosniff”.
Let’s see how to advertise this header.
Apache
You can do this by adding the below line in httpd.conf file
Header set X-Content-Type-Options nosniff
Don’t forget to restart the Apache webserver to get the configuration active.
Nginx
Add the following line in nginx.conf file under server block.
add_header X-Content-Type-Options nosniff;
As usual, you got to restart the Nginx to check the results.
Microsoft IIS
Open IIS and go to HTTP Response Headers
Click on Add and enter the Name and Value
![iis-mime-types](https://geekflare.com/wp-content/uploads/2016/10/iis-mime-types.png)
Click OK and restart the IIS to verify the results.
HTTP Public Key Pinning
Minimize the man-in-the-middle (MITM) attacks risk by pinning certificate. This is possible with HPKP (HTTP Public Key Pinning) header.
You can pin the root certificate public key or immediate certificate. At the time of writing, HPKP currently works in Firefox and Chrome and support SHA-256 hash algorithm.
There are four possible parameter configurations.
Parameter Value | Meaning |
report-uri=”url” | Report to the specified URL if pin validation fails. This is optional. |
pin-sha256=”sha256key” | Specify the pins here |
max-age= | Browser to remember the time in seconds that site is accessible only using one of the pinned keys. |
IncludeSubDomains | This is applicable to a subdomain as well. |
Let’s see HPKP header example from facebook.com
public-key-pins-report-only:max-age=500; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="; pin-sha256="q4PO2G2cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWB8XWQ="; report-uri=http://reports.fb.com/hpkp/
Copy
If this is something you need to implement on your website, then head to the implementation guide written by Scott Helme.
Content Security Policy
Prevent XSS, clickjacking, code injection attacks by implementing the Content Security Policy (CSP) header in your web page HTTP response. CSP instruct browser to load allowed content to load on the website.
All browsers don’t support CSP, so you got to verify before implementing it. There are three ways you can achieve CSP headers.
- Content-Security-Policy – Level 2/1.0
- X-Content-Security-Policy – Deprecated
- X-Webkit-CSP – Deprecated
If you are still using deprecated one, then you may consider upgrading to the latest one.
There are multiple parameters possible to implement CSP, and you can refer to OWASP for an idea. However, let’s go through the two most used parameters.
Parameter Value | Meaning |
default-src | Load everything from a defined source |
script-src | Load only scripts from a defined source |
The following example of loading everything from the same origin in various web servers.
Apache
Get the following added in httpd.conf file and restart the webserver to get effective.
Header set Content-Security-Policy "default-src 'self';"
Nginx
Add the following in the server block in nginx.conf file
add_header Content-Security-Policy "default-src 'self';";
Microsoft IIS
Go to HTTP Response Headers for your respective site in IIS Manager and add the following
![iis-csp](https://geekflare.com/wp-content/uploads/2016/10/iis-csp.png)
X-Permitted-Cross-Domain-Policies
Using Adobe products like PDF, Flash, etc.? You can implement this header to instruct the browser how to handle the requests over a cross-domain. By implementing this header, you restrict loading your site’s assets from other domains to avoid resource abuse.
There are a few options available.
Value | Description |
none | no policy is allowed |
master-only | allow only the master policy |
all | everything is allowed |
by-content-only | Allow only a certain type of content. Example – XML |
by-ftp-only | applicable only for an FTP server |
Apache
If you don’t want to allow any policy.
Header set X-Permitted-Cross-Domain-Policies "none"
Copy
You should see the header like the following.
![](https://geekflare.com/wp-content/uploads/2016/10/permitted-cross-domain.png)
Nginx
And, let’s say you need to implement master-only then add the following in nginx.conf
under server
block.
add_header X-Permitted-Cross-Domain-Policies master-only;
Copy
And the result.
![](https://geekflare.com/wp-content/uploads/2016/10/nginx-permitted-cross.png)
Referrer-Policy
Looking to control the referrer-policy of your site? There are certain privacy and security benefits. However, not all the options are supported by all the browsers, so review your requirements before the implementation.
Referrer-Policy supports the following syntax.
Value | Description |
no-referrer | Referrer information will not be sent with the request. |
no-referrer-when-downgrade | The default setting where referrer is sent to the same protocol as HTTP to HTTP, HTTPS to HTTPS. |
unsafe-url | full URL will be sent with the request. |
same-origin | Referrer will be sent only for same origin site. |
strict-origin | send only when a protocol is HTTPS |
strict-origin-when-cross-origin | the full URL will be sent over a strict protocol like HTTPS |
origin | send the origin URL in all the requests |
origin-when-cross-origin | send FULL URL on the same origin. However, send only origin URL in other cases. |
Apache
You can add the following if you want to set no-referrer.
Header set Referrer-Policy "no-referrer"
Copy
And after the restart, you should have in the response headers.
![](https://geekflare.com/wp-content/uploads/2016/10/referrer-policy-apache.png)
Nginx
Let’s say you need to implement same-origin, so you got to add the following.
add_header Referrer-Policy same-origin;
Copy
Once configured, you should have the results below.
![](https://geekflare.com/wp-content/uploads/2016/10/referrer-nginx-same-origin.png)
Expect-CT
A new header still in experimental status is to instruct the browser to validate the connection with web servers for certificate transparency (CT). This project by Google aims to fix some of the flaws in the SSL/TLS certificate system.
The following three variables are available for Expect-CT header.
Value | Description |
max-age | In seconds, for how long the browser should cache the policy. |
enforce | An optional directive to enforce the policy. |
report-uri | Browser to send a report to the specified URL when valid certificate transparency not received. |
Apache
Let’s assume you want to enforce this policy, report, and cache for 12 hours then you got to add the following.
Header set Expect-CT 'enforce, max-age=43200, report-uri="https://somedomain.com/report"'
Copy
And, here is the result.
![](https://geekflare.com/wp-content/uploads/2016/10/expect-ct-apache-http.png)
Nginx
What if you want to report and cache for 1 hour?
add_header Expect-CT 'max-age=60, report-uri="https://mydomain.com/report"';
Copy
The output would be.
![](https://geekflare.com/wp-content/uploads/2016/10/expect-ct-nginx.png)
Feature-Policy
Control browser’s features such as geolocation, fullscreen, speaker, USB, autoplay, speaker, vibrate, microphone, payment, vr, etc. to enable or disable within a web application.
Apache
Let’s say you need to disable the fullscreen feature, and to do so, you can add the following in httpd.conf or apache2.conf.
Header always set Feature-Policy "fullscreen 'none' "
Copy
How about adding multiple features in a single line?
That’s possible too!
Header always set Feature-Policy "fullscreen 'none'; microphone 'none'"
Copy
Restart Apache HTTP to see the result.
![](https://geekflare.com/wp-content/uploads/2016/10/apache-feature-plicy.png)
The above code will instruct the browser to disable fullscreen and microphone.
Nginx
Let’s take another example – disable vibrate feature.
add_header Feature-Policy "vibrate 'none';";
Copy
Or, disable geolocation, camera, and speaker.
add_header Feature-Policy "geolocation 'none'; camera 'none'; speaker 'none';";
Copy
Here is the output after restarting Nginx.
![](https://geekflare.com/wp-content/uploads/2016/10/nginx-feature-policy.png)
All the Nginx configuration goes under http
block in nginx.conf or any custom file you use.
Conclusion
Securing a website is challenging, and I hope by implementing the above headers, you add a layer of security. If you are running a business site, then you may also consider using cloud-WAF like SUCURI to protect your online business. The good thing about SUCURI is it offers security and performance, both.