Hardening HTTP Response Headers on Apache, Nginx and cPanel

HTTP Response headers is the information that HTTP servers shows you back when you request content from HTTP or HTTPS  protocols. On this post you will learn how to start hardening HTTP response headers

HTTP Response headers are used to get technical information about the software running on the server, type of cache configured, security policies used, among many other things.

This is a typical HTTPS header response:

[webtech@localhost ~]$ curl -I https://nixcp.com
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 06 Feb 2017 13:39:50 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Link: <https://nixcp.com/wp-json/>; rel="https://api.w.org/"
Strict-Transport-Security: max-age=15724800; includeSubdomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Content-Security-Policy: default-src https: data: 'unsafe-inline' 'unsafe-eval'
[webtech@localhost ~]$

As you see, there are lot of details like HTTP version (HTTP/1.1), the web page status response (200 OK), type of web server we use (Nginx), type of content, gzip content, as well as HTTPS security policies (HSTS, X-Frame-Options, CORS, XSS Protection and CSP).

Let’s see to start hardening HTTP response headers with a few simple changes inside your web server configuration

Step by step: Hardening HTTP Response Headers on your Website

One of the first practices for hardening HTTP response headers is to hide essential information about your web server. On the following steps we will see how to reduce server name information, as well as PHP information exposure.

Hide your Web Server Version

Apache information can be reduced to its minimum by tweaking this variables inside httpd.conf file. This is critical if you plan to begin hardening HTTP response headers because the less information you show, the less chances you are targeted by cracking bots and 3rd party individuals.

If you are using cPanel, can be done from here:

WHM » Service Configuration » Apache Configuration » Global Configuration

Then search for: “Server Signature” and “Server Tokens”. Set ‘Server Signature’ to:  Off and ‘Server Tokens’ to ProductOnly

Hiding Apache version information from WHM - Apache Configuration
Eg. 02. Screenshot of Apache Configuration from WHM tweaking Server Tokens and Server Signature options.

If you are using plain Apache you can edit httpd.conf file, usually located at /etc/httpd/conf/httpd.conf

Nginx version information can be hidden by altering ‘server_tokens’ variable.

The server_tokens directive can be set inside a http, server or location block. This reduces server information by hidding nginx version, but still shows the server name.

Example:

server {
...
server_tokens off;
...
}

Hide your PHP information

To avoid showing extra information about the PHP version you are using you can disable expose_php variable from your php.ini configuration.

php.ini file depends entirely on your the way you run PHP. If you are using cPanel + Apache, you may edit /usr/local/lib/php.ini file, or edit it via WHM » Service Configuration » PHP Configuration Editor » Advanced Mode, as you see in the image below:

Hardening HTTP Response Headers by altering expose_php variable on php.ini file
Eg. 01. Screenshot of WHM PHP Configuration Editor configuring expose_php variable.

On other platforms like php-fpm on CentOS you can edit it by running:

nano -w /etc/php.ini

Then locate the following line and change it from this:

expose_php = On

To this:

expose_php = Off

Save the changes by pressing CTRL + X, then Y.

Restart Apache or PHP-FPM to apply changes:

service httpd restart

or

service php-fpm restart

HSTS

You should consider enabling HTTP Strict Transport Security (HSTS). This mechanism forces browsers to communicate using HTTPS protocol only. HSTS let you force your browsers visitors to use HTTPS instead of HTTP. This is really useful to minimize the risk of man in the middle attacks.

Enable HSTS on Apache

First you have to load the mod_headers.so into your Apache configuration if it isn’t already there

LoadModule headers_module modules/mod_headers.so

Then, you can set this the HSTS header inside your vhost configuration, example:

Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;"

Enable HSTS on Nginx

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

‘always’ option is used to make sure that the heaer is set for all responses, including internal generated error responses.

Full example:

server {
    listen 443 ssl;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    }

Content Security Policy

Content Security Policy (CSP) header let you define the list of whitelisted sources of content used by your site.

CSP allows you to restrict the resources any browser can load from your website, this includes CSS and JS for example. This is very useful to mitigate XSS attacks. This is a basic CSP policy that will help you to force TLS on all loaded resources to prevent mixed content issues.

Enable CSP on Apache

Inside your vhost configuration file, place this line:

Header always set Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'"

Enale CSP on Nginx

add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always;

If you need to know about advanced CSP configurations, check out this link.

X-Xss-Protection

X-Xss-Protection header is used to protect your website against XSS attacks. X-Xss-Protection is configured to help the reflective XSS protection that comes by default on Chrome, Safari and IE browsers.

Apache users can enable the X-Xss-Protection header using:

Header always set X-Xss-Protection "1; mode=block"

Nginx users can place this inside their vhost configuration:

add_header X-Xss-Protection "1; mode=block" always;

If you ever need to disable this, you can simply set 1 to 0.

X-Frame-Options

Remember the time when the websites where built using iframes? If you are a new developer you won’t probably have records of that, but I do remember the times when iframes were massively used on webpages.

Today it’s pretty much weird to see iframes on modern websites, but there a a few ocassions when you can see iframes, most of the times they are used to launch clickjacking attacks.

Attackers can upload an iframe on their website and the source of the iframe will be your site. This can be done really easy using this code, for example:

<iframe src=”https://nixcp.com”></iframe>

After that, they can use really tricky techniques to get your login information when you place all your sensitive data.

The X-Frame-Options header can be implemented to use DENY or SAMEORIGIN to allow your own website to use iframes. On this example, we will configure the X-Frame-Options header to SAMEORIGIN.

Enable X-Frame-Options on Apache

Header always set X-Frame-Options "SAMEORIGIN"

Enable X-Frame-Options on Nginx

add_header X-Frame-Options "SAMEORIGIN" always;

Read more about  X-Frame-Options header from here.

X-Content-Type-Options

X-Content-Type-Options header can be configured to prevent browsers from doing MIME-type sniffing. This is only useful and works on IE and Chrome/Chromium web servers.

X-Content-Type-Options header prevents “mime” based attacks. With the nosniff option, if the server says the content is text/html, the browser will render it as text/html. This reduces the chances of renaming content, and treat it as it is, and not as other possible dangerous files, like executables.

X-Content-Type-Options configuration for Apache users:

Header always set X-Content-Type-Options "nosniff"

X-Content-Type-Options configuration for Nginx users:

add_header X-Content-Type-Options "nosniff" always;

Apply changes

Remember to restart apache and nginx after you make all this changes, otherwise you won’t see any changes in your website headers.

Conclusion

Hardening HTTP response headers isn’t hard at all. You just need to know what are the right variables to tweak to avoid exposing too much information from your web server and php server. The most “complicated” part is the TLS/SSL hardening, but if you do it carefully reviewing each option you will probably won’t face any issues.

About the Author: Santiago Borges

Experienced Sr. Linux SysAdmin and Web Technologist, passionate about building tools, automating processes, fixing server issues, troubleshooting, securing and optimizing high traffic websites.

Leave a Reply

Your email address will not be published. Required fields are marked *