Web server security – Part 2: Harden the web server

Web server security – Part 2: Harden the web server

In the first part of this series, we showed you how to harden your server by configuring your firewall and SSH. In this part, we show you how to secure your web server software.

Contents

  1. Requirements
  2. Step by step guide for a more secure web server
  3. Summary

Always stay in the loop!
Subscribe to our RSS/Atom feeds.

Requirements

  • server configured like we described in part 1
  • web server software (Apache, nginx etc.)
  • SSH client on your computer

Step by step guide for a more secure web server

Last time, we configured a general purpose system. You can use this setup to install your own Nextcloud server, OpenVPN server and more. In the following, we use this setup to install an Apache web server.

Please note that there may be another folder structure, other file names or other service names. This depends on your operating system. We will use Apache on Debian 9 in this series.

Step 1: Install Apache and configure Certbot

Web server software processes HTTP and HTTPS requests and sends responses. There are different methods defined in the protocols which we will discuss later. As mentioned before, we use Apache web server. Nginx is also very common. There is no 100% secure web server and configuration is basically the same.

Choose the web server you like and install it according to guides available on the internet. On Debian 9, we install Apache:

  • $ sudo apt update
  • $ sudo apt install apache2

This installs Apache 2.4.25 and several packages needed by Apache. Furthermore, the setup enables several Apache modules by default.

Moreover, we install Certbot which is needed to easily obtain a TLS certificate:

  • $ sudo apt install python-certbot-apache

After installing Certbot, we have to configure our firewall Ufw again. In the first part of this series, we only allowed an IP subnet to connect to port 22 of our server. Common ports for HTTP and HTTPS are port 80 and port 443. Allow all IP addresses to connect to these ports:

  • $ sudo ufw allow 80 (HTTP)
  • $ sudo ufw allow 443 (HTTPS)

Then, you can run Certbot to obtain a certificate:

  • $ sudo certbot --authenticator webroot --installer apache --rsa-key-size 4096

Now you have to enter:

  • the domain name of your website
  • a valid e-mail address which allows Let’s Encrypt to contact you

After that, read and accept the Terms of Service of Let’s Encrypt and choose “1: Enter a new webroot”. Finally, you have to enter the webroot (= folder) of your Apache web server. On Debian, this is most likely /var/www/html/. Certbot tries to get the certificate and offers to configure HTTPS-only: “2: Secure - Make all requests redirect to secure HTTPS access”.

Now, you can enter your domain name in a web browser and you should be automatically redirected to your HTTPS-only demo website of Apache.

Please note that the default setup only covers the domain entered above. It doesn’t cover the “www” resp. “non-www” version of your website. We will fix this in an upcoming part of this series.

Step 2: Configure apache2.conf

HTTPS is only one of many security-related topics when you set up and run your own web server. Let’s continue with other important settings. You find your apache2.conf file in /etc/apache2/apache2.conf on Debian 9. This file contains all basic settings for Apache.

In order to activate HTTP/2 over TLS, you have to enable the HTTP/2 module of Apache first: $ sudo a2enmod http2.

Apply the settings below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[…]
# Global configuration
#

# Enable HTTP/2 over TLS and HTTP/1.1
Protocols h2 http/1.1

[…]

#
# Timeout: The number of seconds before receives and sends time out.
# (Changed from 300 to 60)
Timeout 60

[…]

<Directory /var/www/>
        # clients can't directly access folder contents anymore
        Options -Indexes
        # disable HTTP entity tags (ETags) which can be used to track users
        # and expose sensitive server information
        FileETag None
        # add the following if you want to deploy only static content and
        # users can't post anything. This setting disables all HTTP methods
        # except GET and HEAD.
        <LimitExcept GET>
                deny from all
        </LimitExcept>

        # default values
        AllowOverride None
        Require all granted
</Directory>
[…]

Save apache2.conf and restart the web server: $ sudo systemctl restart apache2.

Step 3: Configure security.conf

Most of your configuration files are located in /etc/apache2/conf-enabled/. This folder contains files of enabled modules.

In order to manipulate HTTP headers, you have to enable the headers module of Apache first: $ sudo a2enmod headers.

Open your security.conf file and apply the following settings:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[…]
# Send only necessary header responses
ServerTokens Prod

[…]

# Reduces server signature which exposes your OS and web server information
# like "Apache/2.4.25 (Debian) Server" to "Apache"
ServerSignature Off

[…]

# Add security-related HTTP headers
# The following settings are fine for static blogs but have to be modified
# for Wordpress etc.

# Enable Content Security Policy
Header always set Content-Security-Policy "default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'"

# Disable Referrer which isn't needed when you don't use authentication
Header always set Referrer-Policy "no-referrer"

# Enable HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

# Enable Clickjacking protection
Header always set X-Frame-Options "DENY"

# Enable XSS protection
Header always set X-Xss-Protection "1; mode=block"

# Enforce MIME types for script and style elements
Header always set X-Content-Type-Options "nosniff"

# Enable OCSP stapling
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/apache2/ocsp(128000)

[…]

Save security.conf and restart the web server: $ sudo systemctl restart apache2.

Step 4: Configure security2.conf

In step 3, we reduced the server signature to “Apache”. To completely disable the signature, we have to install ModSecurity. ModSecurity is an open-source web application firewall which we will discuss in an upcoming article.

Install ModSecurity $ sudo apt install libapache2-modsecurity and open the security2.conf file in /etc/apache2/mods-enabled/. Apply the following setting:

1
2
3
4
[…]
        # Disable the server signature
        SecServerSignature " "
</IfModule>

Save security2.conf and restart the web server: $ sudo systemctl restart apache2.

Step 5: Validate your configuration

After configuring, it is important to test whether the configuration was successfully applied. We wrote an article dedicated to online assessment tools for web server security. Use these tools to check your configuration.

Keep in mind that we didn’t configure TLS, cipher suites and OCSP Must-Staple so far. We will do this in the next part.

Follow us on Mastodon:
@infosechandbook

Step 6: Back up your configuration

Finally, we want to back up our configuration. This is really useful in case of errors or lockout since you can reinstall your server and web server without configuring everything from scratch.

We use a small bash script for this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/bin/bash
mkdir apache
sudo scp -i ~/.ssh/[SSH ID] -r [REMOTE USER]@[IP ADDRESS OF YOUR SERVER]:/etc/apache2/* apache/
mkdir letsencrypt
sudo scp -i ~/.ssh/[SSH ID] -r [REMOTE USER]@[IP ADDRESS OF YOUR SERVER]:/etc/letsencrypt/* letsencrypt/

DATE=$(date +"%F_%H:%M:%S")
zip -r "$DATE-conf-backup.zip" apache/ letsencrypt/

sudo rm -rf apache/
sudo rm -rf letsencrypt/

Save this to a file on your local computer, modify it and execute it after configuration changes. This script creates a local copy of your Apache and Let’s Encrypt configuration.

This article is part of the "Web server security" series.
Read other articles of this series.

Summary

You can start to place your website in /var/www/html. We installed Apache and hardened its configuration. However, this isn’t all about web server security. In the next part, we discuss certificates, TLS, OCSP and other security-related headers in detail.

Remember: Your web server is publicly accessible and just another computer. This means that you have to regularly check for updates and keep your server software up to date!

See also