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.
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.
# for modules sudo service apache2 restart # for configuration changes sudo service apache2 reload
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.
sudo vi /etc/apache2/conf-enabled/security.conf # Set the following options/values to turn off information disclosure ServerTokens Prod ServerSignature Off TraceEnable Off Header unset Server Header unset X-Powered-By
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.
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.
# Change owner and group of DocumentRoot to www-data recursively (www-data is the Apache2 user on Ubuntu) $ sudo chown -R www-data:www-data /var/www/yourapp/ # Set default permissions for everyone recursively # Note that www-data doesn't always need write permissions, try 440 first to tighten permissions even more. $ sudo chmod -R 640 /var/www/yourapp/ # user=read/write, group=read, other=none # Set execute rights for user and group to folders (required) and files that where executable before # Note the capital X - lower case x would set execute permissions for every file instead! $ sudo chmod -R u+X /var/www/yourapp/ $ sudo chmod -R g+X /var/www/yourapp/
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.
$ sudo ls -lah dokuwiki/ total 92K drwxr-x--- 8 www-data www-data 4.0K Sep 18 11:11 . drwxr-xr-x 15 www-data www-data 4.0K Sep 18 11:10 .. drwxr-x--- 2 www-data www-data 4.0K Sep 18 11:10 bin drwxr-x--- 2 www-data www-data 4.0K Sep 18 11:10 conf -rw-r----- 1 www-data www-data 18K Sep 18 11:10 COPYING drwxr-x--- 12 www-data www-data 4.0K Sep 18 11:11 data -rw-r----- 1 www-data www-data 3.6K Sep 18 11:10 doku.php -rw-r----- 1 www-data www-data 19K Sep 18 11:10 feed.php -rw-r----- 1 www-data www-data 1.5K Sep 18 11:10 .htaccess.dist drwxr-x--- 7 www-data www-data 4.0K Sep 18 11:10 inc -rw-r----- 1 www-data www-data 182 Sep 18 11:10 index.php drwxr-x--- 8 www-data www-data 4.0K Sep 18 11:10 lib -rw-r----- 1 www-data www-data 306 Sep 18 11:11 README drwxr-x--- 5 www-data www-data 4.0K Sep 18 11:10 vendor -rw-r----- 1 www-data www-data 23 Sep 18 11:11 VERSION $ ls -lah dokuwiki/ ls: cannot open directory dokuwiki/: Permission denied
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.
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.
<VirtualHost IP:443> ServerAdmin firstname.lastname@example.org ServerName yourserversname # Disable DocumentRoot if Proxy is used! (see below) DocumentRoot /var/www/yourapp/ # SSL/TLS Settings - requires module "ssl" SSLEngine on SSLCertificateFile /etc/ssl/private/ssl-certificate.crt SSLCertificateKeyFile /etc/ssl/private/ssl-certificate.key SSLCACertificateFile /etc/ssl/private/cacert.pem ### Reverse Proxy Settings, requires modules "proxy" and "proxy_http" ### Apache can act as SSL/TLS proxy for your HTTP only applications. #SSLProxyEngine On #ProxyPreserveHost On #ProxyRequests Off #ProxyPass / http://host:port/ #ProxyPassReverse / http://host:port/ ErrorLog "|/usr/bin/logger -p local2.error -t apache" CustomLog "|/usr/bin/logger -p local2.notice -t apache" common # Header Settings - requires module "headers" # If you use HTTPS and have a valid certificate, enabling HSTS is strongly advised! (15768000 seconds = 6 months) Header always set Strict-Transport-Security "max-age=15768000" # Depending on your setup, you might even want to go further than that and choose the following Header options instead. # Header always set Strict-Transport-Security "max-age=15768000; includeSubdomains; preload" # Note that includeSubdomains can cause trouble, if your subdomains are not running on HTTPS, use mixed-content or don't have a valid SSL/TLS certificate! </VirtualHost>
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.
TLS needs more than just a certificate to be secure. The TLS configuration options described below can be appended to following file.
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.
# Disable the old and weak/broken protocols SSLv2 and SSLv3. Instead, the web server will use TLSv1.0, TLSv1.1 and TLSv1.2 SSLProtocol all -SSLv2 -SSLv3 # Define secure list of availabel Ciphers to choose from SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK # Honor = Choose Web Server Cipher choice over clients preferences (http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslhonorcipherorder) SSLHonorCipherOrder on # Disable SSL compression to avoid CRIME attack - http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#sslcompression SSLCompression off # OCSP stapling allows clients to check a certificates revocation status - https://en.wikipedia.org/wiki/OCSP_stapling # OCSP Stapling, is only available in Apache 2.3.3 and later SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000)
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).
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
that start with the following configuration.
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.
$ sudo netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 414/sshd tcp6 0 0 :::22 :::* LISTEN 414/sshd tcp6 0 0 :::443 :::* LISTEN 20646/apache2
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!