Gunicorn: Ability to mask the http response header Server attribute

Created on 24 Jul 2014  ·  36Comments  ·  Source: benoitc/gunicorn

Right now, all responses have the http header
server: gunicorn/19.0.0

For security reasons, I would like to be able to mask that so that people won't know to search for security vulnerabilities in gunicorn. Is there any way to mask it? via a setting perhaps?

Improvement FeaturCore To DO

Most helpful comment

Unfortunately, @mathiasverhoeven closed his PR for some reason and hasn't had activity lately.

Would it be impossible to have more generic option here, as in --set-headers where you can specify any amount of headers as key-value pairs? Empty value would omit the header completely.

At the moment, I would like to adjust Server, but I would also like to add one more response header, e.g. X-Product: MyProduct.

I can throw something together based on @mathiasverhoeven's PR. @benoitc and @tilgovi what do you think?

All 36 comments

Typically gunicorn is deployed behind a reverse proxy server like nginx in production environment, and nginx would output its own Server tag.

upstair plus one

with @benoitc we can propose an option on the command line, what do you think? otherwise, we will close this ticket as explained by @georgexsh , in production mode, you can use a reverse proxy (nginx, apache, ...).

Couldn't one just modify the environ in a post_request hook?

@tilgovi that would work I guess... not sure then if we need to create another option...

Doesn't work. The request is sent already at that point.

@tilgovi middleware wont work too, because Server is in default headers.

What if we just remove the Server header altogether?

+1

If we allow you to set the header's value to a random string, we should also allow you to remove the header completely.

+1

why do you want to remove the header?

In the past, I've removed the header from deployments to hide the server software and version so that it doesn't get picked up by someone crawling for servers with a known exploit.

Yup. Security is one of the reasons. Of course, you can change the Server value to something random, but why send extra bytes that aren't really necessary?

I took the liberty to make a PR for this feature: #1384 . It has been on my wanted list for some time.

To add to the discussion: I would argue that while some reverse proxy servers modify the Server header, some add a Via header like described in https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.38

Unfortunately, @mathiasverhoeven closed his PR for some reason and hasn't had activity lately.

Would it be impossible to have more generic option here, as in --set-headers where you can specify any amount of headers as key-value pairs? Empty value would omit the header completely.

At the moment, I would like to adjust Server, but I would also like to add one more response header, e.g. X-Product: MyProduct.

I can throw something together based on @mathiasverhoeven's PR. @benoitc and @tilgovi what do you think?

Just going to leave this here: https://www.fastly.com/blog/headers-we-dont-want. As you can read in the article, the Server header is both very common AND completely unnecessary.

I would also like to be able to omit the Server header. I use a security-focused webserver called Hiawatha to reverse proxy, set not to add a Server header of its own, so gunicorn's Server header is currently making it to clients.

@tuukkamustonen's idea sounds good to me. :)

Edit: just seen https://github.com/benoitc/gunicorn/pull/1617. server_tokens = true|false|string would be great.

Anyone running Flask? https://stackoverflow.com/a/46858238/452210 suggests wrapping and overriding process_response, replacing or removing the header.

I would also like to be able to omit the Server header. I use a security-focused webserver called Hiawatha to reverse proxy, set not to add a Server header of its own, so gunicorn's Server header is currently making it to clients.

I noticed that even cloudflare is displaying a Server header, so i'm not sure these days how it is more about security than fame.

I think that rather than adding another option to the command line or config i would simply remove the version from the header for a start. Then add a configuration file only setting to remove the server_token. Advantage of it is that server gracefully upgrading to the new version will be able to add that setting without stopping the service. Thoughts?

I noticed that even cloudflare is displaying a Server header, so i'm not sure these days how it is more about security than fame.

I think Cloudflare's service and server header has a different context to that of an individual site's server. When a site is reverse-proxied to via Cloudflare, the fact that it's Cloudflare that's doing the proxying is not otherwise unknown; it's apparent via nameservers and/or IP address, etc. In contrast, me hosting a site on a VPS with no third party reverse proxy does potentially afford me some hope of avoiding at least direct identification via HTTP header of the server software. (The thinking being, of course, that if gunicorn is in future found to have some vulnerability, finding targets should be more difficult than merely searching for its server header.)

I think that rather than adding another option to the command line or config i would simply remove the version from the header for a start. Then add a configuration file only setting to remove the server_token. Advantage of it is that server gracefully upgrading to the new version will be able to add that setting without stopping the service. Thoughts?

That would be great. :+1: :slightly_smiling_face:

Yes please at least remove version. Version adds nothing to fame and saves a lot of time for attackers.

I am thinking to just remove the version. @tilgovi any thoughts on it?

Fine for me!

Any progress on this one? This seems like a quick win for security.

that will be part of the next 20.1

I am thinking to just remove the version.

Is the configuration file-only setting to remove the Server header altogether still planned?

@DavidOliver why the question?

@benoitc Your comment which I quoted could be interpreted to mean that it's "just"/only the version number which will be removed, whereas earlier in the conversation the setting to remove the Server header altogether (which I'd like to do) was being considered.

Thanks.

If we can just remove the server header altogether, we should do it.

I still have to be convinced that removing it has something to do with the
security. It has not been an issue in the last 10 years. Security by
obscurity doesn't help also, I would prefer to know we have an issue and
fix it. Also knowing the server can help the operations

I'm inclined to remove the version at the moment as this version is giving
too much information on how the server is maintained. We should do it for
each branch we maintained.

Thoughts?

Benoît

On Sun 29 Dec 2019 at 04:23 Randall Leeds notifications@github.com wrote:

If we can just remove the server header altogether, we should do it.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/benoitc/gunicorn/issues/825?email_source=notifications&email_token=AAADRIQBGN2KQRKOKLAYK43Q3AJ2PA5CNFSM4ASCOWF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHYW27Q#issuecomment-569470334,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAADRISEUFGD43CKXLV3EZTQ3AJ2PANCNFSM4ASCOWFQ
.

>

Sent from my Mobile

Hi,

I'm using gunicorn to serve responses over a connection where data
is expensive, anything I can remove is anything I don't have to pay.

The Server header is small, but small things add up, and sometimes
small things means you can fit everything in one-less packet: the
server header with version is 24 bytes, about 1.7% of the payload
with a MSS of 1460 and TLS headers. Even without the extra packet,
a larger packet is much more likely to need to be entirely resent
when the connection is bad (like a cellular network in a remote place).

On a fresh HTTPS connection, the handshake and certificate
exchange make most of the payload and small things can be
ignored. For small repeated requests using keep-alive, redundant
headers become a much larger part of the request/response.

This might also matter for people who care more about client
performance (latency more than throughput) than cost.

For this use case, the most useful option is to be able to
entirely remove the header, not simply removing the value
or the version part.

This comment is mostly limited to adding relevant reference/spec/RFC information, and (hopefully) mostly unopinionated interpretation/commentary.

RFC7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content https://tools.ietf.org/html/rfc7231#section-7.4.2

...An origin server MAY generate a Server field in its responses.

An origin server SHOULD NOT generate a Server field containing needlessly fine-grained detail and SHOULD limit the addition of subproducts by third parties. Overly long and detailed Server field values increase response latency and potentially reveal internal implementation details that might make it (slightly) easier for attackers to find and exploit known security holes.

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

9.6. Disclosure of Product Information
The User-Agent (Section 5.5.3), Via (Section 5.7.1 of [RFC7230]), and Server (Section 7.4.2) header fields often reveal information about the respective sender's software systems. In theory, this can make it easier for an attacker to exploit known security holes; in practice, attackers tend to try all potential holes regardless of the apparent software versions being used. Proxies that serve as a portal through a network firewall ought to take special precautions regarding the transfer of header information that might identify hosts behind the firewall. The Via header field allows intermediaries to replace sensitive machine names with pseudonyms.

From (deprecated) RFC2616:

15.1.2 Transfer of Sensitive Information
Like any generic data transfer protocol, HTTP cannot regulate the content of the data that is transferred, nor is there any a priori method of determining the sensitivity of any particular piece of information within the context of any given request. Therefore, applications SHOULD supply as much control over this information as possible to the provider of that information. Four header fields are worth special mention in this context: Server, Via, Referer and From.
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.

PEP3333 Python Web Server Gateway Interface v1.0.1 https://www.python.org/dev/peps/pep-3333/#the-start-response-callable

In general, the server or gateway is responsible for ensuring that correct headers are sent to the client: if the application omits a header required by HTTP (or other relevant specifications that are in effect), the server or gateway must add it. For example, the HTTP Date: and Server: headers would normally be supplied by the server or gateway.

  • The Server response header is optional according to HTTP 1.1
  • The RFC recognises that overly-detailed Server fields can make it easier to scan sites for vulnerable servers. Clearly this is a make-it-one-step-harder, obscurity provision, and how-much-detail is too much is circumstantial.
  • Deprecated HTTP 1.1 RFC2616 is a little bolder in the value of hiding the Server header.
  • PEP3333 seems to overstep slightly when mentioning the Server header in the context of required or normal headers.

Plenty of opinion on this, such as in Apache HTTPD ServerTokens: https://httpd.apache.org/docs/2.4/mod/core.html#servertokens

Setting ServerTokens to less than minimal is not recommended because it makes it more difficult to debug interoperational problems. Also note that disabling the Server: header does nothing at all to make your server more secure. The idea of "security through obscurity" is a myth and leads to a false sense of safety.

Changing the server header to just say gunicorn is a practical solution and I think we should do that, with no configuration.

People like @kmichel-sereema, who want to optimize the size of every transfer, I think this is not the place to perform such micro-optimization. If the HTTP headers are too much overhead, HTTP 1.x is the not the ideal protocol to use, and I don't think we should add additional configuration to allow changing or disabling the server header.

The suggestion of @tilgovi seems like a good compromise to me.

In many environments this may even be moot. The gunicorn deployment documents recommend having a proxy server like nginx in front of gunicorn. nginx automatically strips the Server response header from the proxied server before it goes to the client, and can be configured to strip more headers. Surely more security-focused proxies can do the same.

following my suggestion and comments from @tilgovi & @jamadden I'm closing this issue favor of #2233. Thanks all for the code and comments!

Was this page helpful?
0 / 5 - 0 ratings