Bug 58750 - Provide way to disable Server header completely
Summary: Provide way to disable Server header completely
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.0.30
Hardware: PC Mac OS X 10.1
: P2 enhancement with 31 votes (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-17 17:23 UTC by Rob Winch
Modified: 2022-01-21 13:10 UTC (History)
2 users (show)



Attachments
Suggested patch (1.80 KB, patch)
2015-12-18 11:10 UTC, Phillip Webb
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rob Winch 2015-12-17 17:23:06 UTC
Tomcat currently allows overriding the Server attribute, but does not allow removing the Server header completely. It would be valuable from a security perspective to be able to remove the header completely. 

One might argue this provides little value (it is security through obscurity). In my opinion there is a big difference on relying on obscurity and preventing information leakage. If your security depends on obscurity (i.e. that is the only security measure you take), then I think we can agree this is bad.

Most agree that security is best in depth. To me this means preventing information leakage (removing the header) does provide value.

Users could set the Tomcat header to something non nonsensical, but this gives information away too. Most servers provide a way to disable the header completely, so this reveals that the user is likely using an application server that does not support it.

References:

https://www.owasp.org/index.php/Information_Leakage
http://www.acunetix.com/blog/articles/configure-web-server-disclose-identity/
https://github.com/spring-projects/spring-boot/issues/4730 (see comments)
Comment 1 Remy Maucherat 2015-12-17 17:28:19 UTC
Indeed, this provides absolutely no value :)
Comment 2 Mark Thomas 2015-12-17 19:50:53 UTC
I don't see any significant information leakage here, even if the exact Tomcat version is provided.

Assume you have a Tomcat instance running 8.0.30 (no known vulnerabilities as I type this). How does it make that instance less secure (easier to attack) if the attacker knows that it is a Tomcat 8.0.30 instance vs. now knowing what server it is?

The best answer I can come up with is that the attacker doesn't have to waste time trying out known vulnerabilities for other servers or earlier Tomcat versions but that doesn't make the Tomcat instance any easier to attack. It might mean that the attacker gets spotted and blocked while they test various known vulnerabilities but internet facing servers get hit with so many scans that unless an attacker generates so many requests it starts to have a DoS effect the scans are simply ignored. Automating blocking is only used for the worst offenders because NAT and proxies means blocking every 'attack' shuts out large numbers of legitimate users which is actually much worse than just ignoring the scan.

It is also worth noting that because many system admins fake the server header, most attackers try scanning for all known vulnerabilities anyway.

Now consider a Tomcat instance running 8.0.0 vulnerable to CVE-2014-0050 (DoS). Hiding the server header doesn't make the Tomcat instance any less vulnerable to the DoS. It may take an attacker slightly longer to find vulnerability, but - given my comments above - they are going to find it anyway.

In short, hiding the server header is a waste of time (even for instances running insecure versions) that would be better spend upgrading insecure instances to secure versions.

I'd be more than happy to reconsider my position and implement this feature if a valid case is made for how hiding the server header increases the actual security of an instance.
Comment 3 Rob Winch 2015-12-17 21:52:14 UTC
Thank you for the responses.

> It is also worth noting that because many system admins fake the server header, most attackers try scanning for all known vulnerabilities anyway.

Some hackers may target specific applications. If that is the approach they are taking, they are likely to try all exploits against the victim. As already mentioned, exposing information will likely help them prioritize the exploits to find something more quickly which will increase the likely hood that they go undetected.

Hackers don't always target a specific victim. Another method of attack is to have a known set of vulnerabilities and actively searching for victims. Exposing any unnecessary information makes it easier for the attacker to find victims in an automated way.



> In short, hiding the server header is a waste of time (even for instances 
> running insecure versions) that would be better spend upgrading insecure 
> instances to secure versions.

This isn't always possible. For example, there may be a 0-day exploit that has no patched version or was just released & users have not had the opportunity to update. Hackers are going to easily be able to find victims if the Server header is exposed.



> Indeed, this provides absolutely no value :)

> In short, hiding the server header is a waste of time (even for instances
> running insecure versions) that would be better spend upgrading insecure
> instances to secure versions.

These seem like pretty bold claims. I'd be very interested in seeing some citations.

I can provide countless credible citations that recommend removing the Server header. I have provided a few additional examples below.

= OWASP

I provided this citation on the original report. However, since OWASP is such an important part of web application security, I felt like this should be emphasized.

OWASP states that "Information Leakage" is a class of vulnerability [1]. It is described as:

    Revealing system data or debugging information helps an adversary learn
    about the system and form a plan of attack. An information leak occurs
    when system data or debugging information leaves the program through an
    output stream or logging function.

From my perspective, the Server header is revealing unnecessary information. This means it fits the OWASP description of "Information Leakage" and should be removed.

= Troy Hunt (Microsoft MVP for Developer Security, etc)

I an excellent article by Troy Hunt (Microsoft MVP for Developer Security, etc) on why you should remove unnecessary HTTP headers from the response [2]. Some highlights of the article include:

* Why removing headers is not "security through obscurity"
* A concrete example of how exposing headers can help find victims of 0-day exploits
* Additional citations on why headers that leak information should be removed

= RFC-2616 "15.1.2 Transfer of Sensitive Information"

The IETF recommends that server implementations SHOULD make the Server header a configurable option [3].

   Revealing the specific software version of the server might allow the
   server machine to become more vulnerable to attacks against software
   that is known to contain security holes. Implementors SHOULD make the
   Server header field a configurable option.




[1] https://www.owasp.org/index.php/Information_Leakage
[2] http://www.troyhunt.com/2012/02/shhh-dont-let-your-response-headers.html
[3] http://www.rfc-base.org/txt/rfc-2616.txt

Regards,
Rob Winch
Comment 4 Konstantin Kolinko 2015-12-18 03:05:55 UTC
1. The place to patch is 
org.apache.coyote.http11.Http11Processor.prepareResponse()

If this feature is enabled, then it means that
1) if none Server header is set by a web application, we should skip adding the default one
2) if a Server header was set by a web application, we should remove it

2. A possible value to trigger this feature could be setting an empty string,
but that value is already used as a synonym for no value (null),
by Http11Processor.setServer() setter method.


3. For reference, the Server header is defined for HTTP/1.1 by RFC 7231 ch.7.4.2.

https://tools.ietf.org/html/rfc7231#section-7.4.2

A server "MAY" generate it. There is no obligation to actually generate it. Skipping the Server header saves several bytes of bandwidth.
Comment 5 Phillip Webb 2015-12-18 09:56:10 UTC
I'm trying to create a patch for this but I don't seem to be able to build 8.0.x from trunk.

Running `ant test` gives me:

test-bio:

BUILD FAILED
/Users/pwebb/projects/tomcat/trunk/build.xml:1374: The following error occurred while executing this line:
/Users/pwebb/projects/tomcat/trunk/build.xml:1431: junit doesn't support the "threads" attribute


Any ideas?
Comment 6 Mark Thomas 2015-12-18 09:59:55 UTC
Read BUILDING.txt for details on the minimum Ant version required.
Comment 7 Phillip Webb 2015-12-18 10:00:53 UTC
Thanks! Sorry, I should have checked that.
Comment 8 Remy Maucherat 2015-12-18 10:06:01 UTC
"2) if a Server header was set by a web application, we should remove it": I see no reason to do that.
Comment 9 Mark Thomas 2015-12-18 10:15:53 UTC
I remain unconvinced that there are any real world security benefits to be gained by removing the security header.

The bandwidth argument carries slightly more weight but we are only talking 27 bytes per response and most responses will dwarf that by at least several orders of magnitude. Add HTTP/2 to the mix and those 27 bytes will quickly shrink.

If we do anything at all, I am leaning towards completely removing all Server header processing (all ~15 lines of code of it) and let applications add it if they wish. Users wanting to provide useful server version information via configuration can enable the X-Powered-By header.
Comment 10 Phillip Webb 2015-12-18 10:55:13 UTC
Thanks! Sorry, I should have checked that.
Comment 11 Phillip Webb 2015-12-18 11:04:15 UTC
Removing all server header processing code will break back compatibility. Specifically, this recently added Spring Boot feature [1] will stop working since it relies on the `server` attribute being picked up.

[1] https://github.com/spring-projects/spring-boot/issues/4461
Comment 12 Phillip Webb 2015-12-18 11:08:53 UTC
For more information about what's driving this request see https://github.com/spring-projects/spring-boot/issues/4730. We've specifically looking for feature parity across all embedded servlet containers that we support (Tomcat, Jetty, Undertow).

I think the least invasive option is to add a flag to disable the server header. This would be similar to Jetty's `HttpConfiguration.setSendServerVersion`, not effect any existing users and provide a quick way to opt-out of the header.
Comment 13 Phillip Webb 2015-12-18 11:10:08 UTC
Created attachment 33364 [details]
Suggested patch

Something like this. (not including tests yet as not sure where to add them)
Comment 14 Phillip Webb 2015-12-18 16:29:25 UTC
I've been mulling this issue over a little bit more and I think that the arguments about whether removing the header offers any real world security or bandwidth benefits are a bit of a red herring. There's clearly some difference of opinion here, but regardless of why you'd want to remove the header, it still stands that it's currently not possible.

If we put the argument of why to one side, and just focus on answering the question "How do I remove the server header?", what are the options? Is the suggested patch a sensible approach? Is there some other way to do it (a custom Http11Protocol implementation? some way to post-process headers?).

I'm happy to try and rework the patch as required, or try to find a less invasive way to solve the problem. My ultimate goal is to just prove the request Spring Boot feature without needing to add a "but not on Tomcat" caveat.
Comment 15 Mark Thomas 2015-12-18 17:41:33 UTC
Ignoring the reasoning isn't a red herring. It is part of deciding what the best solution is. "Because someone wants it" is not, on its own, sufficient justification.

The patch looks like a good start if we wanted to go that way. It needs some docs.

However, I'm still leaning towards removing all server header handling from Tomcat. That gives users - including boot - maximum flexibility. They can add/remove the header as desired via the Servlet API. We can remove the server option completely in 9.0.x. In 8.0.x and earlier I think we'd need to set the header if the option is set to retain backwards compatibility. Essentially that changes Tomcat's default behaviour from sending the header to not sending it.

In the (unlikely) case of an app setting the header that the system administrator wants to remove, the sys admin would need to add a filter that removed the header.
Comment 16 Christopher Schultz 2015-12-22 23:40:35 UTC
(In reply to Mark Thomas from comment #9)
> I remain unconvinced that there are any real world security benefits to be
> gained by removing the security header.

Agreed.

> The bandwidth argument carries slightly more weight but we are only talking
> 27 bytes per response and most responses will dwarf that by at least several
> orders of magnitude. Add HTTP/2 to the mix and those 27 bytes will quickly
> shrink.

While the bytes shrink, the CPU still gets wasted to shrink them.

An even better argument *for* a configurable parameter might be HTTP spec. Section 15.1.2 of RFC 2616 pretty much says flat-out that servers SHOULD make the Server header a configurable option. But, RFC 7231 says nothing similar so I'd call it a draw from a spec perspective.
Comment 17 Greg Turnquist 2015-12-31 17:36:37 UTC
I tend to lean towards security experts (like OWASP) that indicate it's preferable to reduce information leakage, rather than simply asserting there is no real world risk here.

The rest of the industry has headed towards reducing information leakage (see Jetty, Undertow, etc.) While "everyone else is doing it" isn't an argument, observing an industry migration that is backed up by cited security experts IS an argument in favor of such a change.

On a personal note, it's interesting that we're not concerned about 27 bytes because it's nothing, but some ARE concerned about the cycles spent to generate those 27 bytes. I don't think resource consumption is the focal point of this request, being premature optimization. I would favor upholding RFCs behind servlets as well as HTTP headers alongside industry-driven security recommendations, and save optimization only for AFTER that has been met.
Comment 18 Anthony J. Biacco 2016-03-07 23:28:32 UTC
I usually just modify server.* org/apache/catalina/util/ServerInfo.properties and rebuild catalina.jar.
Not exactly ideal, but fairly trivial for me at least to mask the info.
Comment 19 Anthony J. Biacco 2016-03-07 23:35:20 UTC
Sorry, i don't REBUILD the jar, i just leave org/apache/catalina/util/ServerInfo.properties there after modded as suggested in the Valves section of https://tomcat.apache.org/tomcat-8.0-doc/security-howto.html
Comment 20 Phillip Webb 2016-04-07 17:57:21 UTC
FWIW we're still getting quite a bit of interest in this on the Spring Boot issue tracker. It seems like a fair number would like the ability to not send the header.
Comment 21 Mark Thomas 2016-05-23 19:57:59 UTC
Tomcat 9.0.x and 8.5.x no longer set the Server header by default.
Setting the server attribute on a Connector still replaces any value specified by the web application.
A new attribute serverRemoveAppProvidedValues allows any application specified value to be removed.

This change will be included in:
- 9.0.0.M7 onwards
- 8.5.3 onwards