Web server fingerprinting is the task of identifying the type and version of web server that a target is running on. While web server fingerprinting is often encapsulated in automated testing tools, it is important for researchers to understand the fundamentals of how these tools attempt to identify software, and why this is useful.
Accurately discovering the type of web server that an application runs on can enable security testers to determine if the application is vulnerable to attack. In particular, servers running older versions of software without up-to-date security patches can be susceptible to known version-specific exploits.
Determine the version and type of a running web server to enable further discovery of any known vulnerabilities.
How to Test
Techniques used for web server fingerprinting include banner grabbing, eliciting responses to malformed requests, and using automated tools to perform more robust scans that use a combination of tactics. The fundamental premise by which all these techniques operate is the same. They all strive to elicit some response from the web server which can then be compared to a database of known responses and behaviors, and thus matched to a known server type.
A banner grab is performed by sending an HTTP request to the web server and examining its response header. This can be accomplished using a variety of tools, including telnet for HTTP requests, or openssl for requests over SSL.
For example, here is the response to a request from an Apache server.
HTTP/1.1 200 OKDate: Thu, 05 Sep 2019 17:42:39 GMTServer: Apache/2.4.41 (Unix)Last-Modified: Thu, 05 Sep 2019 17:40:42 GMTETag: "75-591d1d21b6167"Accept-Ranges: bytesContent-Length: 117Connection: closeContent-Type: text/html...
Here is another response, this time from nginx.
HTTP/1.1 200 OKServer: nginx/1.17.3Date: Thu, 05 Sep 2019 17:50:24 GMTContent-Type: text/htmlContent-Length: 117Last-Modified: Thu, 05 Sep 2019 17:40:42 GMTConnection: closeETag: "5d71489a-75"Accept-Ranges: bytes...
Here’s what a response from lighttpd looks like.
HTTP/1.0 200 OK Content-Type: text/html Accept-Ranges: bytes ETag: "4192788355" Last-Modified: Thu, 05 Sep 2019 17:40:42 GMT Content-Length: 117 Connection: close Date: Thu, 05 Sep 2019 17:57:57 GMT Server: lighttpd/1.4.54
In these examples, the server type and version is clearly exposed. However, security-conscious applications may obfuscate their server information by modifying the header. For example, here is an excerpt from the response to a request for a site with a modified header:
HTTP/1.1 200 OK Server: Website.com Date: Thu, 05 Sep 2019 17:57:06 GMT Content-Type: text/html; charset=utf-8 Status: 200 OK ...
In cases where the server information is obscured, testers may guess the type of server based on the ordering of the header fields. Note that in the Apache example above, the fields follow this order:
However, in both the nginx and obscured server examples, the fields in common follow this order:
Testers can use this information to guess that the obscured server is nginx. However, considering that a number of different web servers may share the same field ordering and fields can be modified or removed, this method is not definite.
Sending Malformed Requests
Web servers may be identified by examining their error responses, and in the cases where they have not been customized, their default error pages. One way to compel a server to present these is by sending intentionally incorrect or malformed requests.
For example, here is the response to a request for the non-existent method SANTA CLAUS from an Apache server.
GET / SANTA CLAUS/1.1 HTTP/1.1 400 Bad Request Date: Fri, 06 Sep 2019 19:21:01 GMT Server: Apache/2.4.41 (Unix) Content-Length: 226 Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>400 Bad Request</title> </head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> </p> </body></html>
Here is the response to the same request from nginx.
GET / SANTA CLAUS/1.1 <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.17.3</center> </body> </html>
Here is the response to the same request from lighttpd.
GET / SANTA CLAUS/1.1 HTTP/1.0 400 Bad Request Content-Type: text/html Content-Length: 345 Connection: close Date: Sun, 08 Sep 2019 21:56:17 GMT Server: lighttpd/1.4.54 <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>400 Bad Request</title> </head> <body> <h1>400 Bad Request</h1> </body> </html>
As default error pages offer many differentiating factors between types of web servers, their examination can be an effective method for fingerprinting even when server header fields are obscured.
Using Automated Scanning Tools
As stated earlier, web server fingerprinting is often included as a functionality of automated scanning tools. These tools are able to make requests similar to those demonstrated above, as well as send other more server-specific probes. Automated tools can compare responses from web servers much faster than manual testing, and utilize large databases of known responses to attempt server identification. For these reasons, automated tools are more likely to produce accurate results.
Here are some commonly-used scan tools that include web server fingerprinting functionality.
Netcraft, an online tool that scans websites for information, including the web server.
Nikto, an Open Source command-line scanning tool.
Nmap, an Open Source command-line tool that also has a GUI, Zenmap.
While exposed server information is not necessarily in itself a vulnerability, it is information that can assist attackers in exploiting other vulnerabilities that may exist. Exposed server information can also lead attackers to find version-specific server vulnerabilities that can be used to exploit unpatched servers. For this reason it is recommended that some precautions be taken. These actions include:
Obscuring web server information in headers, such as with Apache’s mod_headers module.
Using a hardened reverse proxy server to create an additional layer of security between the web server and the Internet.
Ensuring that web servers are kept up-to-date with the latest software and security patches.