Apache Explained
Apache Explained
So recently, an Intern at our company asked me several question about Apache web server and SSL certificates. I decided to do a blog post on the same and hopefully you’ll also get to learn a thing or two. With that said, let me breakdown what this blog post entails.
- Installing Apache WebServer
- Apache Logs
- Creating SSL Certificates
- Securing your webserver
Installing Apache WebServer
In this walkthrough, i will be using a clean install of Ubuntu 20.04 LTS. By default, the Apache web root or Document root folder location is at /var/www/html. On a clean server however, we dont have the /www/html
directories.
To install Apache webserver, simply run:
sudo apt install apache2
With that done, we need to start the service.
If we now load the server’s ip on the browser, we should get the default It Works! page.
I know many of you dont read this page.😅
I see you. But this page contains some good information related to the web server. Such information includes:
- The configuration layout for an Apache2 web server installation
- Explanation on different config files and binaries.
Don’t worry, i’ll walk you through them.
Apache Configuration Layout
Before we get into the flesh, lets do a few network configurations. We need to assign a static ip for our webserver.
Since this server uses netplan
as its default network management tool, we can get the configuration file in /etc/netplan
. Before we make any changes to the config file, you need to make a backup copy of the same incase you need to revert back to its original state. You can then use a text editor of your choice to edit the file. In our case, we will assign the server an IP of 192.168.1.50 as shown in the snippet below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dev@dev:/etc$ cd netplan/
dev@dev:/etc/netplan$ ls -la
total 12
drwxr-xr-x 2 root root 4096 Apr 23 13:00 .
drwxr-xr-x 100 root root 4096 Apr 23 13:46 ..
-rw-r--r-- 1 root root 116 Apr 23 13:00 00-installer-config.yaml
dev@dev:/etc/netplan$ sudo cp 00-installer-config.yaml 00-installer-config.yaml.bak
[sudo] password for dev:
dev@dev:/etc/netplan$ cat 00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
ethernets:
ens33:
dhcp4: true
version: 2
Modify the configuration file to resemble the one below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dev@dev:/etc/netplan$ sudo vi 00-installer-config.yaml
dev@dev:/etc/netplan$ cat 00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
version: 2
renderer: networkd
ethernets:
ens33:
dhcp4: no
addresses:
- 192.168.1.50/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
dev@dev:/etc/netplan$ sudo netplan apply
After saving changes, run the sudo netplan apply
command for changes to apply.
NB:For a few seconds, you will be disconnected from your session and required to ssh back in using the set IP
For practice purposes, lets also modify our hostname to theoffice.com
1
2
3
4
5
6
7
8
dev@dev:~$ cat /etc/hostname
dev
dev@dev:~$ sudo vi /etc/hostname
[sudo] password for dev:
dev@dev:~$ cat /etc/hostname
theoffice.com
dev@dev:~$ reboot
After the reboot, our server will now be recognized across the network as theoffice.com
. We can confirm changes took place by running the command below:
1
2
3
dev@theoffice:~$ hostname
theoffice.com
dev@theoffice:~$
We also need to make some changes on the hosts file as highlighted below:
Since the ubuntu server doesnt have a UI, we need to map that domain on my windows hosts file in order to resolve the site. The hosts file in windows is located in C:\Windows\System32\drivers\etc
.
If we save the changes and visit the domain, it works.
With that done, we’re going to leave the default Apache virtual host configuration pointing to theoffice.com
and set up a subdomain called pass.theoffice.com
We start by creating a directory in /var/www/
called pass. I’m just gonna clone a random password generator project from github that we can quickly host on this VHOST.
1
2
3
4
dev@theoffice:~$ cd /var/www/
dev@theoffice:/var/www$ sudo mkdir pass
[sudo] password for dev:
dev@theoffice:/var/www$ cd pass/
Transfer the files required to that directory
1
2
3
4
5
6
7
8
9
dev@theoffice:/var/www/pass$ ls -la
total 28
drwxr-xr-x 5 root root 4096 Apr 23 15:35 .
drwxr-xr-x 4 root root 4096 Apr 23 15:33 ..
drwxr-xr-x 2 root root 4096 Apr 23 15:34 css
drwxr-xr-x 2 root root 4096 Apr 23 15:34 images
-rw-r--r-- 1 root root 3693 Apr 23 15:34 index.html
drwxr-xr-x 2 root root 4096 Apr 23 15:34 js
-rw-r--r-- 1 root root 205 Apr 23 15:34 README.md
By default, as seen earlier, apache comes with its default site which can be found in the /var/www/html directory and its configuration files can be found in /etc/apache2/sites-enabled/000-default.conf
But before we look at the configuration file, i feel like its important first to understand the /etc/apache2/
directory structure.
sites-available
and sites-enabled
are directories used for managing virtual hosts.
- The
sites-available
directory contains configuration files for all the available virtual hosts on the server. These configuration files define the settings for each virtual host, such as the domain name, document root, and any other directives required to serve the site. - The
sites-enabled
directory contains symbolic links to the configuration files of the virtual hosts that are currently enabled on the server. These symbolic links are created to activate a particular virtual host. Enabling a site simply means creating a symbolic link from the configuration file in thesites-available
directory to thesites-enabled
directory.
We then need to create a VirtualHost file for our VHOST. To do this, we can navigate to /etc/apache2/sites-available/
. Since Apache came with a default VirtualHost file, let’s use that as our base config file and create a replica which we can modify.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dev@theoffice:/var/www/pass$ cd /etc/apache2/sites-available/
dev@theoffice:/etc/apache2/sites-available$ ls -la
total 20
drwxr-xr-x 2 root root 4096 Apr 23 13:46 .
drwxr-xr-x 8 root root 4096 Apr 23 13:46 ..
-rw-r--r-- 1 root root 1332 Feb 23 2021 000-default.conf
-rw-r--r-- 1 root root 6338 Feb 23 2021 default-ssl.conf
dev@theoffice:/etc/apache2/sites-available$ sudo cp 000-default.conf pass.conf
dev@theoffice:/etc/apache2/sites-available$ ls -la
total 24
drwxr-xr-x 2 root root 4096 Apr 23 15:52 .
drwxr-xr-x 8 root root 4096 Apr 23 13:46 ..
-rw-r--r-- 1 root root 1332 Feb 23 2021 000-default.conf
-rw-r--r-- 1 root root 6338 Feb 23 2021 default-ssl.conf
-rw-r--r-- 1 root root 1332 Apr 23 15:52 pass.conf
I named my config file pass.conf
to match our VHOST name.
By default, the config file looks like this:
Here, we want the DocumentRoot
directive to point to the directory our site files are hosted on.
The default file doesn’t come with a ServerName
directive so we’ll have to add and define it by adding this line below the DocumentRoot
Since our files are already on the directory, we need to activate the virtual hosts configuration file to enable it. We do that by running the following command in the configuration file directory:
1
2
3
4
5
dev@theoffice:/etc/apache2/sites-available$ sudo a2ensite pass.conf
Enabling site pass.
To activate the new configuration, you need to run:
systemctl reload apache2
dev@theoffice:/etc/apache2/sites-available$ sudo systemctl reload apache2
To load the new site, you need to restart the webserver.
a2ensite
is a script that enables the specified site (which contains a < VirtualHost > block) within the apache2 configuration. It does this by creating symlinks within/etc/apache2/sites-enabled
.
While at it
a2dis-site
disables a site by removing those symlinks. It is not an error to enable a site which is already enabled, or to disable one which is already disabled.
If we now navigate to pass.theoffice.com
on our browser, we should be able to access our website.
Creating SSL certificate
We can create a self-signed SSL/TLS certificate in Linux using the OpenSSL command line tool. Here are the steps to create a self-signed certificate:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@theoffice:/home/dev# openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650
Generating a RSA private key
....++++
......................................................................................................................................................................................................................................................................................................................................................................++++
writing new private key to 'key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KE
State or Province Name (full name) [Some-State]:Nairobi
Locality Name (eg, city) []:Nairobi
Organization Name (eg, company) [Internet Widgits Pty Ltd]:The Office
Organizational Unit Name (eg, section) []:dev
Common Name (e.g. server FQDN or YOUR name) []:theoffice.com
Email Address []:dev@theoffice.com
A short explanation of the command above:
-x509
: This option generates a self-signed certificate.-newkey rsa:4096
: This option generates a new RSA 4096-bit key for the certificate.-keyout key.pem
: This option specifies the filename for the private key.-out cert.pem
: This option specifies the filename for the certificate.-sha256
: This option specifies the hash algorithm to use for the certificate.-days 3650
: This option sets the expiration date for the certificate to 10 years (3650 days) from the current date.
A common location to store SSL/TLS certificates in Apache is /etc/ssl/certs
, while the corresponding private keys are typically stored in /etc/ssl/private
.
1
2
root@theoffice:/etc/apache2/sites-available# cp /home/dev/key.pem /etc/ssl/private
root@theoffice:/etc/apache2/sites-available# cp /home/dev/cert.pem /etc/ssl/cert
We also need to modify our VHOST configuration file again to reference the certificate files Inside the VirtualHost block as shown below:
Apache has a tool called apachectl
that we can use to test if our configuration has correct syntax and directives. In my case, i got an error regarding SSLEngine
.
1
2
3
4
5
root@theoffice:/etc/apache2/sites-available# apachectl -t
AH00526: Syntax error on line 14 of /etc/apache2/sites-enabled/pass.conf:
Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
Action '-t' failed.
The Apache error log may have more information.
A quick google search, i learn that this is caused by the fact that the server’s basic configuration does not have mod_ssl module
installed/enabled which is responsible for creating and serving SSL connections.
A quick fix for this is simply running sudo a2enmod ssl
as shown:
1
2
3
4
5
6
7
8
9
10
11
12
root@theoffice:/etc/apache2/sites-available# a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
systemctl restart apache2
root@theoffice:/etc/apache2/sites-available#
This should fix the problem. If we now test our configuration file, we should get a Syntax OK
1
2
3
root@theoffice:/etc/apache2/sites-available# apachectl -t
Syntax OK
root@theoffice:/etc/apache2/sites-available#
Now lets restart apache. This time, we’ll be prompted to enter a passphrase for SSL/TLS keys
1
2
root@theoffice:/etc/apache2/sites-available# systemctl restart apache2
Enter passphrase for SSL/TLS keys for pass.theoffice.com:443 (RSA): *********
We are now able to visit our VHOST over https. 😎
Now that we are deploying certs, why dont we do it with Security in mind.😎
With help from the following resources, i was able to add the following entries outside the < VirtualHost> block.
- SSL/TLS Strong Encryption: How-To - Apache
- Configuring a Cipher Suites List Using TLS v1.2 and Earlier
- Mozilla SSL Config Generator
- Security/Server Side TLS
- How to install an SSL Certificate on Apache
In a nutshell, i’ll try explain what each of the above entries mean.
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
- SSL 3.0 and TLS 1.0 are susceptible to known attacks on the protocol; they are disabled entirely. Disabling TLS 1.1 is (as of August 2016) mostly optional; TLS 1.2 provides stronger encryption options, but 1.1 is not yet known to be broken. Disabling 1.1 may mitigate attacks against some broken TLS implementations.- Enabling
SSLHonorCipherOrder
ensures that the server’s cipher preferences are followed instead of the client’s. - Disabling
SSLSessionTickets
ensures Perfect Forward Secrecy is not compromised if the server is not restarted regularly. - Disabling
SSLCompression
prevents TLS compression oracle attacks (e.g. CRIME). SSLUseStapling On
- Enabling OCSP Stapling improves performance by providing the clients with up-to-date status of your certificate.SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
- Specifies the OCSP cache response location and size.SSLCipherSuite HIGH:!SSLv2:!RC4:!aNULL@STRENGTH
- The SSLCipherSuite directive is used in the Apache configuration file to specify the list of SSL/TLS cipher suites that are allowed for SSL/TLS connections.!RC4
- Specifies not to use any RC4 suites.HIGH
- Specifies that only cipher suites using strong encryption should be allowed. The HIGH value is a shorthand for a list of cipher suites that use AES, Camellia, and other strong encryption algorithms.!aNULL
- This specifies that cipher suites that allow null authentication (i.e., no authentication of the server or client) should not be used.!SSLv2
- This specifies that SSLv2 should not be used, as it is an insecure protocol that is susceptible to a number of vulnerabilities.@STRENGTH
: This specifies that cipher suites should be listed in order of strength, with the strongest cipher suites listed first.
In order to test our ssl
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
➜ sslscan https://pass.theoffice.com
Version: 2.0.15-static
OpenSSL 1.1.1q-dev xx XXX xxxx
Connected to 192.168.1.50
Testing SSL server pass.theoffice.com on port 443 using SNI name pass.theoffice.com
SSL/TLS Protocols:
SSLv2 disabled
SSLv3 disabled
TLSv1.0 disabled
TLSv1.1 disabled
TLSv1.2 enabled
TLSv1.3 enabled
TLS Fallback SCSV:
Server supports TLS Fallback SCSV
TLS renegotiation:
Session renegotiation not supported
TLS Compression:
Compression disabled
Heartbleed:
TLSv1.3 not vulnerable to heartbleed
TLSv1.2 not vulnerable to heartbleed
Supported Server Cipher(s):
Preferred TLSv1.3 256 bits TLS_AES_256_GCM_SHA384 Curve 25519 DHE 253
Accepted TLSv1.3 256 bits TLS_CHACHA20_POLY1305_SHA256 Curve 25519 DHE 253
Accepted TLSv1.3 128 bits TLS_AES_128_GCM_SHA256 Curve 25519 DHE 253
Preferred TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-GCM-SHA384 DHE 4096 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-CHACHA20-POLY1305 DHE 4096 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM8 DHE 4096 bits
Accepted TLSv1.2 256 bits DHE-RSA-AES256-CCM DHE 4096 bits
Accepted TLSv1.2 256 bits ECDHE-ARIA256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-ARIA256-GCM-SHA384 DHE 4096 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA256 DHE 4096 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-CAMELLIA256-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA256 DHE 4096 bits
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-SHA Curve 25519 DHE 253
Accepted TLSv1.2 256 bits DHE-RSA-AES256-SHA DHE 4096 bits
Accepted TLSv1.2 256 bits DHE-RSA-CAMELLIA256-SHA DHE 4096 bits
Accepted TLSv1.2 256 bits AES256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-CCM8
Accepted TLSv1.2 256 bits AES256-CCM
Accepted TLSv1.2 256 bits ARIA256-GCM-SHA384
Accepted TLSv1.2 256 bits AES256-SHA256
Accepted TLSv1.2 256 bits CAMELLIA256-SHA256
Accepted TLSv1.2 256 bits AES256-SHA
Accepted TLSv1.2 256 bits CAMELLIA256-SHA
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-GCM-SHA256 DHE 4096 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM8 DHE 4096 bits
Accepted TLSv1.2 128 bits DHE-RSA-AES128-CCM DHE 4096 bits
Accepted TLSv1.2 128 bits ECDHE-ARIA128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-ARIA128-GCM-SHA256 DHE 4096 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA256 DHE 4096 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-CAMELLIA128-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA256 DHE 4096 bits
Accepted TLSv1.2 128 bits ECDHE-RSA-AES128-SHA Curve 25519 DHE 253
Accepted TLSv1.2 128 bits DHE-RSA-AES128-SHA DHE 4096 bits
Accepted TLSv1.2 128 bits DHE-RSA-CAMELLIA128-SHA DHE 4096 bits
Accepted TLSv1.2 128 bits AES128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-CCM8
Accepted TLSv1.2 128 bits AES128-CCM
Accepted TLSv1.2 128 bits ARIA128-GCM-SHA256
Accepted TLSv1.2 128 bits AES128-SHA256
Accepted TLSv1.2 128 bits CAMELLIA128-SHA256
Accepted TLSv1.2 128 bits AES128-SHA
Accepted TLSv1.2 128 bits CAMELLIA128-SHA
Server Key Exchange Group(s):
TLSv1.3 128 bits secp256r1 (NIST P-256)
TLSv1.3 192 bits secp384r1 (NIST P-384)
TLSv1.3 260 bits secp521r1 (NIST P-521)
TLSv1.3 128 bits x25519
TLSv1.3 224 bits x448
TLSv1.2 128 bits secp256r1 (NIST P-256)
TLSv1.2 192 bits secp384r1 (NIST P-384)
TLSv1.2 260 bits secp521r1 (NIST P-521)
TLSv1.2 128 bits x25519
TLSv1.2 224 bits x448
SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength: 4096
Subject: theoffice.com
Issuer: theoffice.com
Not valid before: Apr 23 16:55:12 2023 GMT
Not valid after: Apr 20 16:55:12 2033 GMT
We can also use nmap
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
nmap -p 443 --script ssl-cert,ssl-enum-ciphers pass.theoffice.com
Nmap scan report for pass.theoffice.com (192.168.1.50)
Host is up (0.00088s latency).
rDNS record for 192.168.1.50: theoffice.com
PORT STATE SERVICE
443/tcp open https
| ssl-cert: Subject: commonName=theoffice.com/organizationName=The Office/stateOrProvinceName=Nairobi/countryName=KE
| Issuer: commonName=theoffice.com/organizationName=The Office/stateOrProvinceName=Nairobi/countryName=KE
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-04-23T16:55:12
| Not valid after: 2033-04-20T16:55:12
| MD5: 93c1442a5091523bb2c2131f60cd49e5
|_SHA-1: 340755f163d86343b23ea3d4ca28e1f81495931a
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (dh 4096) - A
| TLS_DHE_RSA_WITH_AES_256_CCM_8 (dh 4096) - A
| TLS_DHE_RSA_WITH_AES_256_CCM (dh 4096) - A
| TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 4096) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 4096) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 4096) - A
| TLS_RSA_WITH_AES_256_CCM_8 (rsa 4096) - A
| TLS_RSA_WITH_AES_256_CCM (rsa 4096) - A
| TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 4096) - A
| TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 4096) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 4096) - A
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 4096) - A
| TLS_DHE_RSA_WITH_AES_128_CCM_8 (dh 4096) - A
| TLS_DHE_RSA_WITH_AES_128_CCM (dh 4096) - A
| TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (dh 4096) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 4096) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 4096) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_AES_128_CCM_8 (rsa 4096) - A
| TLS_RSA_WITH_AES_128_CCM (rsa 4096) - A
| TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 4096) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 4096) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 4096) - A
| compressors:
| NULL
| cipher preference: server
| TLSv1.3:
| ciphers:
| TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| cipher preference: server
|_ least strength: A
MAC Address: 00:0C:29:28:C3:2B (VMware)
Nmap done: 1 IP address (1 host up) scanned in 2.84 seconds
Security Headers
‘HTTP Security Response Headers’ allow a server to push additional security information to web browsers and govern how the web browsers and visitors are able to interact with your web application.
Having the appropriate Security Header Response policies in place adds another level of protection that can stop common attacks such as code injection, cross-site scripting attacks and clickjacking. For most CMS sites such as WordPress and hosts using Apache servers, these Header Response policies can be set via the .htaccess
file.
To learn more about security headers, i’ve included some resources that might help.
To begin, lets use a couple of tools to identify missing headers on our VHOST.
Using ZAP, we can see some of the headers and policies not set.
We can also use other tools like Nuclei vulnerability scanner to identify missing headers.
From the output above, we can identify more missing headers. I’m going to walk you through how you can configure/set some of them.
On our VHOST configuration file (pass.conf), we need to the folowing configuration block:
1
2
3
4
5
6
7
8
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *;"
Header set X-XSS-Protection "1; mode=block"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin"
Header always set Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()"
Header always set Clear-Site-Data "cache"
Also, from our Nuclei output, we identified Apache’s ServerToken Directive which discloses Our Apache version information. In order to hide server information in Apache, we can add the following directives to our VHOST configuration file.
1
2
3
# Hiding Apache ServerToken Directive
ServerSignature Off
ServerTokens Prod
I choose to set ServerTokens Prod
as the directive since i dont want people guessing or identifying the exact version.
NB: The config lines should be added outside the < VirtualHost > block as shown.
Other configuration options include:
1
2
3
4
5
6
7
8
9
10
11
12
ServerTokens Full (or not specified)
Server sends (e.g.): Server: Apache/2.4.2 (Unix) PHP/4.2.2 MyMod/1.2
ServerTokens Prod[uctOnly]
Server sends (e.g.): Server: Apache
ServerTokens Major
Server sends (e.g.): Server: Apache/2
ServerTokens Minor
Server sends (e.g.): Server: Apache/2.4
ServerTokens Min[imal]
Server sends (e.g.): Server: Apache/2.4.2
ServerTokens OS
Server sends (e.g.): Server: Apache/2.4.2 (Unix)
With that done, we can save changes made to the file and check if there might be any syntax errors.
1
2
3
4
5
6
root@theoffice:/etc/apache2/sites-available# nano pass.conf
root@theoffice:/etc/apache2/sites-available# apachectl -t
AH00526: Syntax error on line 19 of /etc/apache2/sites-enabled/pass.conf:
Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
Action '-t' failed.
The Apache error log may have more information.
Ooops! Another error 😫. By doing a quick google search, i learnt this is because mod_headers
had not been enabled. To resolve this, we can use the a2enmod
utility to enable the module as shown:
1
2
3
4
root@theoffice:/etc/apache2/sites-available# sudo a2enmod headers
Enabling module headers.
To activate the new configuration, you need to run:
systemctl restart apache2
Apache Module mod_headers provides directives to control and modify HTTP request and response headers. Headers can be merged, replaced or removed.
This time, we can restart the webserver and confirm if the response header fields which is sent back to clients includes a description of the generic OS-type of the server as well as information about compiled-in modules.
Using nmap, we can identify if the headers have propagated as shown:
We can also check if Apache version information has been disabled as shown:
Apache Logs
Apache creates several log files in the /var/log/apache2/
subdirectory.
The :
access.log
file records all requests made to the server to access files.error.log
records all errors thrown by the server.
A typical configuration for the access log might look as follows.
1
2
3
4
5
6
7
8
9
10
root@theoffice:~# cd /var/log/apache2/
root@theoffice:/var/log/apache2# ls -la
total 7860
drwxr-x--- 2 root adm 4096 May 7 12:15 .
drwxrwxr-x 10 root syslog 4096 May 7 11:27 ..
-rw-r----- 1 root adm 7671026 May 7 11:54 access.log
-rw-r----- 1 root adm 362599 May 7 11:54 error.log
root@theoffice:/var/log/apache2# tail access.log
192.168.1.103 - - [07/May/2023:12:18:45 +0000] "GET /.env HTTP/1.1" 404 852 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
192.168.1.103 - - [07/May/2023:12:18:45 +0000] "GET /.git/config HTTP/1.1" 404 852 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
Lets break down the first request and see understand each part of the log entry:
192.168.1.103
- This is the IP address of the client (remote host) which made the request to the server. If HostnameLookups is set to On, then the server will try to determine the hostname and log it in place of the IP address. However, this configuration is not recommended since it can significantly slow the server. Instead, it is best to use a log post-processor such as logresolve to determine the hostnames.[07/May/2023:12:18:45 +0000]
- The time that the request was received. The format is:- [day/month/year:hour:minute:second zone]
- day = 2digit
- month = 3letter
- year = 4digit
- hour = 2digit
- minute = 2digit
- second = 2digit
zone = (+ -) 4*digit
- [day/month/year:hour:minute:second zone]
"GET /.env HTTP/1.1"
- The request line from the client is given in double quotes. The request line contains a great deal of useful information. First, the method used by the client isGET
. Second, the client requested the resource.env
, and third, the client used the protocolHTTP/1.1
.404
- This is the status code that the server sends back to the client. This information is very valuable, because it reveals whether the request resulted in a successful response (codes beginning in 2), a redirection (codes beginning in 3), an error caused by the client (codes beginning in 4), or an error in the server (codes beginning in 5). The full list of possible status codes can be found in the HTTP specification (RFC2616 section 10).852
- The last part indicates the size of the object returned to the client, not including the response headers. If no content was returned to the client, this value will be “-“. To log “0” for no content."Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
- The User-Agent HTTP request header. This is the identifying information that the client browser reports about itself.Mozilla/5.0:
This is the product token and version number that identifies the browser as a version of Mozilla. Many modern browsers use this token in their user agent strings for compatibility reasons.(Windows NT 10.0; Win64; x64):
This is the operating system token, which indicates that the client is running on a 64-bit version of Windows 10. The Win64 and x64 parameters indicate that the operating system and CPU architecture are both 64-bit.AppleWebKit/537.36:
This is the rendering engine token, which identifies the browser’s layout engine. This token indicates that the browser is based on the WebKit engine, which is used by several popular browsers including Chrome and Safari. The version number is 537.36.(KHTML, like Gecko):
This is an optional token that some browsers include to indicate that they are compatible with the rendering engine used by Mozilla Firefox (Gecko) and Konqueror (KHTML).Chrome/113.0.0.0:
This is the browser token, which identifies the specific browser that is being used. In this case, it indicates that the client is using version 113.0.0.0 of the Google Chrome browser.Safari/537.36:
This is an optional token that some browsers include to indicate that they are compatible with the Safari browser. In this case, it indicates that the client is compatible with version 537.36 of Safari’s rendering engine.
- Apache - Log Files
Comments powered by Disqus.