Hide your Nginx Version
Abenezer Belachew · January 14, 2024
5 min read
-
Maybe this is just me being paranoid but hiding the Nginx version wouldn’t hurt. We all know that vulnerabilities are always there. People are sneaky and will eventually always find ways to break things, intentionally or not. I am personally aware of malicious bots that just crawl the web for vulnerabilities looking for their next victim. Often, their tactics are straightforward, such as locating admin pages and attempting brute-force attacks with common username and password combinations, or exploiting unpatched versions of tech stacks in applications.
-
Speaking of tech stakcs, Nginx is a widely used option used in a majority of web services for a variety of applications. Although I hold Nginx in high regard for its reliability, it, like many software platforms, has had to address a number of vulnerabilities over time. This awareness becomes particularly pertinent when considering the information exposed in server response headers. For instance, let’s say I use
nginx/1.18.0
. Making a request to a location served by an Nginx server yields the following response headers. -
Notice how the
Server
header has revealed the version of nginx I’m using and the OS it’s running on. It's generally fine, but hypothetically, if I were embarrassed about the Linux distro my site runs on (which I'm not), I wouldn't want Nginx revealing it to everyone in the response header. -
Who knows? There might even be a distro-specific vulnerability. I don’t want it telling everyone (specially those crawlers) the OS my server is running on. In such a case, the transparency of Nginx in revealing system details in the response header could be a point of concern.
-
But it's not just the operating system that's of concern; the version of the software is equally troubling. Consider the possibility of a vulnerability existing in the current version of Nginx I'm using. Imagine if a critical bug were discovered in
1.18.0
at a time when I am unable to update to a newer version. This situation could be problematic. By displaying the Nginx version in the response header, I inadvertently increase the risk of becoming a target for malicious bots. -
At this stage, by revealing the Nginx version in the response headers, I'm essentially broadcasting to all crawlers and potential attackers that my application might be vulnerable. It's like openly admitting a weakness without any attempt at concealment.
-
So, the pressing question arises: is it possible to avoid disclosing this information, to not let everyone know about potential vulnerabilities?
- Fortunately, the answer is yes, and the solution is surprisingly trivial. 🦎
Let’s hide the version first
- With a simple
server_tokens off
directive in your server block, you can hide the version.
server {
...
# Dontshowtheversionofnginximscaredofgettinghacked
server_tokens off;
...
}
Test your config and reload it:
nginx -t
systemctl reload nginx
And now you’ll see this:
- But can we do better? Can we not have nginx show up under Server header? Can it be something obscure and unrelated?
- Of course it can, it’s Nginx. It’s very customizable. 🦚
- This can be done by simply adding a
add_header Server <server-name>
directive. I named mine Cloudflare because why not. 🤷♂️
server {
...
# Dontshowtheversionofnginximscaredofgettinghacked
server_tokens off;
add_header Server "Cloudflare";
...
}
- Reload nginx.
Now it should look like it’s being routed through Cloudflare. Right?
-
Why are there two
Server
headers? Is that even possible? Turns out, it is. -
There are standard headers that Nginx might include in responses depending on the configuration and situation.
Server
is among them. Now that we know that, we have to find a way to remove theServer
header set by nginx. -
After some searching, I discovered that the
more_clear_headers
directive, available in the nginx-extras package, can accomplish this task. Although I prefer to avoid installing additional dependencies, this appears to be the simplest solution I can find right now. Installation instructions are available for reference. Once you have set up the repository configuration, the specific Nginx module required for this functionality is known asnginx-module-headers-more
.🛑️ If you use
Thanks to David Smedberg for pointing this out to me!apt-get install nginx-extras
to installnginx-extras
, make sure that it doesn't downgrade your Nginx to an older version available in the apt repository.- And then add the
more_clear_headers Server
directive to yourserver
block.
- And then add the
server {
...
# Dontshowtheversionofnginximscaredofgettinghacked
server_tokens off;
add_header Server "Cloudflare";
more_clear_headers Server;
...
}
- Reload nginx.
- Looks like it’s finally working. :)
Note:
- But wait! One more thing. Don't forget to create custom error pages, too, because Nginx happily displays the version it's currently running on these pages too.
- Cloudflare's Server headers actually return
cloudflare
and notCloudflare
. At least that's what it did during the time of writing this article but I am too lazy to change the screenshots. 🤷♂️ - Now you’re a tiny bit safer on the internet. Obviously don't take this as a replacement for proper security practices. This is simply a way to make it a bit harder for attackers to find out what you're running.
Adios! 🐄