Skip to content

Hiding Apache Server Version

One of the services that people working with Linux systems are likely to encounter frequently is web services like Nginx and Apache. In this article, we will see how to completely hide the Apache server version from header information.

Note: The examples in this article will be based on RHEL 9.1 (Plow). On Debian-based distributions, the file names you'll be working with will be different. However, the configuration steps you need to add will be the same.

TL;DR:

Install mod_security. Set ServerTokens to Prod and SecServerSignature to " " (leave it blank). Restart/reload Apache.

After running security scans with tools like Nessus, you might encounter warnings such as "Apache ServerTokens Information Disclosure." What is expected of you is to make some adjustments to ensure that Apache hides certain sensitive information from the other side.

Apache provides an opportunity for this hiding process, but only to a certain extent. At the end of the day, if you are not using any Apache modules, you will have to return "Apache" as the Server Name. There has been a lot of debate on this topic. Some argue that hiding the name is not a security measure, while others believe that this feature should definitely be included. I will leave a few links at the end of the article regarding these discussions.

Origin of the Issue

Let’s quickly set up an Apache installation and send a simple request to this server. Let’s see what we get:

curl response from Apache server

Now, let's use the "curl" program with the "-I" or "--head" parameter to retrieve only the header information:

[root@rhel8-demo html]# curl -I 192.168.1.42
HTTP/1.1 200 OK
Date: Mon, 09 Oct 2023 19:31:27 GMT
Server: Apache/2.4.53 (Red Hat Enterprise Linux)
Last-Modified: Mon, 09 Oct 2023 19:28:57 GMT
ETag: "9d-6074d99f79e48"
Accept-Ranges: bytes
Content-Length: 157
Content-Type: text/html; charset=UTF-8

Header information returned by Apache with default settings

Looking at this output, we can see that the web server in use is Apache 2.4.53 and that it is running on a Red Hat Enterprise Linux device. This kind of information being visible can sometimes be annoying. Now, let’s take a look at how we can change this situation.

Apache ServerTokens Configuration

In the configuration file of your Apache server (by default /etc/httpd/conf/httpd.conf for RHEL-based systems), you can modify the "ServerTokens" directive to change the information Apache presents in the header.

The ServerTokens directive returns all information by default if not specified. We saw an example above. The possible values are:

ServerTokens İşlev
Full All information such as Apache version, OS details, PHP information
Prod Apache
Major Major version number
Minor Minor version number
Min Apache version
OS Apache version and OS information

Let's make these changes in our file and observe the outputs for different settings. Of course, remember that we need to restart or reload the Apache service after making these changes:

[root@rhel8-demo html]# vim /etc/httpd/conf/httpd.conf
[root@rhel8-demo html]# systemctl restart httpd
[root@rhel8-demo html]# echo ServerTokens Full denemesi && curl -I 192.168.1.42
ServerTokens Full denemesi
HTTP/1.1 200 OK
Date: Mon, 09 Oct 2023 19:42:24 GMT
Server: Apache/2.4.53 (Red Hat Enterprise Linux)
Last-Modified: Mon, 09 Oct 2023 19:28:57 GMT
ETag: "9d-6074d99f79e48"
Accept-Ranges: bytes
Content-Length: 157
Content-Type: text/html; charset=UTF-8

[root@rhel8-demo html]# vim /etc/httpd/conf/httpd.conf
[root@rhel8-demo html]# systemctl restart httpd
[root@rhel8-demo html]# echo ServerTokens Prod denemesi && curl -I 192.168.1.42
ServerTokens Prod denemesi
HTTP/1.1 200 OK
Date: Mon, 09 Oct 2023 19:43:05 GMT
Server: Apache
Last-Modified: Mon, 09 Oct 2023 19:28:57 GMT
ETag: "9d-6074d99f79e48"
Accept-Ranges: bytes
Content-Length: 157
Content-Type: text/html; charset=UTF-8

[root@rhel8-demo html]# vim /etc/httpd/conf/httpd.conf
[root@rhel8-demo html]# systemctl restart httpd
[root@rhel8-demo html]# echo ServerTokens Major denemesi && curl -I 192.168.1.42
ServerTokens Major denemesi
HTTP/1.1 200 OK
Date: Mon, 09 Oct 2023 19:43:38 GMT
Server: Apache/2
Last-Modified: Mon, 09 Oct 2023 19:28:57 GMT
ETag: "9d-6074d99f79e48"
Accept-Ranges: bytes
Content-Length: 157
Content-Type: text/html; charset=UTF-8

Different behaviors of the Apache ServerTokens directive

As seen, different header information is returned with different settings. For more detailed information about ServerTokens, you can refer to Apache’s relevant documentation.

Completely Hiding Apache Header Information (SecServerSignature)

Let’s assume you want to completely hide the header information. In this case, you’ll need the "SecServerSignature" directive. If you make the following adjustment in your Apache configuration file:

ServerTokens Prod
SecServerSignature ' '

Although everything seems to be in order, when we perform a syntax check, we will encounter the error Invalid command 'SecServerSignature':

[root@rhel8-demo html]# httpd -t
AH00526: Syntax error on line 37 of /etc/httpd/conf/httpd.conf:
Invalid command 'SecServerSignature', perhaps misspelled or defined by a module not included in the server configuration

The solution is quite simple. It is sufficient to install the mod_security module for Apache.

[root@rhel8-demo html]# yum install mod_security
.................
[root@rhel8-demo html]# httpd -t
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::a00:27ff:feff:9536%enp0s3. Set the 'ServerName' directive globally to suppress this message
Syntax OK

After this step, you will find that the syntax error related to SecServerSignature is resolved, and you'll see a message indicating that the syntax is correct, along with a warning unrelated to our topic.

When you make a curl request, you'll see:

[root@rhel8-demo html]# curl --head 192.168.1.42
HTTP/1.1 200 OK
Date: Mon, 09 Oct 2023 19:52:41 GMT
Server:
Last-Modified: Mon, 09 Oct 2023 19:28:57 GMT
ETag: "9d-6074d99f79e48"
Accept-Ranges: bytes
Content-Length: 157
Content-Type: text/html; charset=UTF-8

You can see that we have completely hidden the Apache server version and name from the header information.

Warning!

  • As with many services, the Apache service also pulls configuration files from various directories (include). If you see no response from the changes you made in the httpd.conf file, ensure that you have restarted the service and that your settings are not being overwritten by different files.
  • When you leave the SecServerSignature directive empty, you will encounter an error like the following:
[root@rhel8-demo html]# httpd -t
AH00526: Syntax error on line 362 of /etc/httpd/conf/httpd.conf:
SecServerSignature takes one argument, the new signature of the server

The reason for this is quite clear. You must provide one argument to this directive. Therefore, make sure to leave a space between the quotation marks. This way, the header will not be empty, but will instead return a space.

Alternatively, instead of leaving the SecServerSignature directive empty, you can also fill it with a different string:

Apache custom SecServerSignature

For further configuration recommendations and tips, you can read the Apache section of the OWASP Secure Configuration Guide.