Quick Guide – Hardening Apache2

This is a quick overview of a secure Apache2 configuration. We won’t be going into Linux hardening, but will focus instead on the basic configuration options of Apache2. The following code boxes show examples of a secure configuration. Please adjust them to your requirements and test each of them before applying them to a live/production system.

The examples below include the web server miss-configurations and weak spots that we most commonly observe during our web applications pentests.

Prerequisites

Before we start changing anything, here is a list of Apache2 modules that are required for these settings. I’ve added comments in the code boxes as to which module is required, so just enabled them according to your requirements.

sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy proxy_html

While enabling modules requires Apache2 to be restarted, a reload of the config files should suffice for changes in the configuration.

Prevent Information Disclosure

Apache2, by default, is rather talkative about its own version. If you hit a 404 site that’s been generated by the server, it usually includes some information about the web server and its version. This is information that could potentially help attackers find weak spots in your server. It’s easy to disable though and is, as far as my experience goes, risk free.

Note that the “Header unset Server” option will still sometimes show the “Server: Apache” header, for example in Apache’s 404 responses. Apache2 itself doesn’t offer an easy way to get rid of these, but the associated risk isn’t all that high either. If you insist on removing it, I suggest using either the module ModSecurity to remove the header completely, or hiding the web server behind a load balancer, such as HAProxy, which offers the same functionality.

While we’re at setting header options, let’s set a few more to increase the security of the web application as well. In the example above we’ve unset headers to remove sensitive information from our HTTP requests. In the next section we will set headers instead, to add security instructions for browsers.

Header set X-Content-Type-Options: "nosniff"
Header set X-Permitted-Cross-Domain-Policies: "master-only"
Header set X-XSS-Protection: "1; mode=block"
# Only set this option if you are not embedding this page somewhere else (e.g. in Owncloud or iFrames on other sites!)
Header set X-Frame-Options: "sameorigin"

This is what I usually set by default on all my servers. The first three are absolute no-brainers and have never cause any problems for me in the past. The X-Frame-Options header should be used to prevent click-jacking attacks, unless your application has to cooperate with one of your other servers, in which case this header could cause some trouble.

For more information, and a quite handy check of your servers header settings, check out securityheaders.io.

File Permissions

This is technically not an Apache2 configuration but important nevertheless and since Apache2 already runs under its own user, www-data, might as well set the permissions right.

Obviously, file permissions should always be set according to the least-privilege principle. This means that the files should only be accessible by whoever needs to access them and permitted actions (read,write,execute) should be limited as much as possible.

So depending on your web application, you should start with the following settings and work your way up the permission chain, until everything is working.

Please note that setting the permissions above can cause problems with delivering your website, so don’t apply them to your production system without testing the application beforehand in a safe environment!

Here is an example with a fresh DokuWiki installation. Note that DokuWiki is rather easy to handle in regards to file permissions. Other applications might require more work to be fully functional.

Since I’m not working as www-data user, I don’t have permission to access the files. However, www-data does have the required permissions to access and write the files, therefore the website is being delivered properly and I have no problem creating new entries.

Default SSL/TLS vHost

Terminology: Just to avoid confusing anyone and to keep this simple. There are two protocols used for HTTPS, both are available in different versions. SSLv2 and SSLv3 have known vulnerabilities, are considered insecure and should therefore not be used any more. TLS comes in three versions, 1.0, 1.1 and 1.2 and is the successor of SSL. Each TLS version tries to do better than the last, but server and browser side adoption is slow and therefore all three versions should be used for now. You will still see the term SSL everywhere though, as most configuration options and tools are still named after it.

Encrypting the traffic from and to your web server is more and more becoming the norm, which is good, as offers great security – if done right. The configuration example below should help you set up HTTPS properly.

The HSTS header is a huge addition to your visitors security if your website runs on HTTPS, however, it can cause trouble if you are using mixed content. So test this header before rolling it out, especially if your website loads content from both HTTPS and HTTP sources. More info on the HSTS preload option can be found on the hstspreload website.

Proper TLS Configuration

TLS needs more than just a certificate to be secure. The TLS configuration options described below can be appended to following file.

/etc/apache2/conf-enabled/security.conf

The configuration described below is deemed secure (2015-09-18), lowering it in favour of compatibility (looking at you, Windows XP/IE6.0) will put all of your users at risk!
The option most prone to updates is probably the SSLCipherSuite selection. For an updated selection of secure ciphers, please refer to the Mozilla SSL Config Generator.

You should test your configuration afterwards using either a current version of sslscan which is available for Windows and in most Linux repositories, most notably KALI,

sslscan --no-failed yourserver.com

or by heading over to Qualys SSL Labs for a detailed online report. Qualys will also show you what devices and browsers are compatible with your TLS settings.

These are good default settings for TLS but there is more. If you want to really ensure secure connections, take a look at HTTP Public Key Pinning (HPKP).

Disable HTTP and Port 80

Now that your website securely runs on HTTPS, you might want to think about disabling HTTP and port 80. Of course, public websites will keep HTTP running, if not for actual content than at least to redirect incoming visitors to HTTPS. But for internal applications that run on HTTPS only, disabling all port 80 vHosts, as well as the port 80 listener can be an improvement to security.

First, make sure to disable all vhosts in

/etc/apache2/sites-enabled/

that start with the following configuration.

<VirtualHost *:80>

Note that the * can be an actual star or something else, depending on your setup. You can either disable them by adding # at the beginning of each line or by disabling the whole file. The latter should obviously only be used, if you keep a separate file for each virtual host.

sudo a2dissite vhostconfigfilename

Once you’ve disabled all HTTP vhosts, you might as well disable port 80 all together to prevent someone accidentally enabling a port 80 vhost again.

sudo vi /etc/apache2/ports.conf
# disable Listen 80 if your server runs on HTTPS only. This is useful for internal web apps, but usually not used by public websites.
# Listen 80

Make sure to restart Apache2 afterwards and check with the following command if Apache2 is still listening on port 80.

That's it!

That should cover the most common miss-configurations. If you’ve gone through all that and applied the settings according to your environment and your requirements then you should be good to go – provided you patch your systems regularly of course!