What a version banner actually contains
The term comes from network diagnostics: a service announces who it is on first contact. On the web that self-description sits in the response headers. The OWASP testing guide calls collecting it banner grabbing and keeps the effort short: an HTTP request is sent to the web server and its response header is examined (OWASP Testing Guide). No account, no privileged tooling, no exploited weakness - one request is enough, and the answer comes from the public page itself. That is exactly why the item appears early in test catalogues: it costs the tester a second and may cost the operator the pre-selection that an attack starts from.
- Server: product name, often the exact version, sometimes the distribution and the modules compiled in.
- X-Powered-By: the runtime behind the application, as a rule including its version number.
- X-AspNet-Version and X-AspNetMvc-Version: the framework version, independent of the web server in front of it.
- X-Server and X-Backend-Server: internal host names that expose the naming scheme of your own environment.
- Via and X-Cache: upstream intermediaries including their product - visible even when the origin server stays silent.
- Error pages: a web server's default page names product and version in its footer, even when the header has long been trimmed.
In the weakness taxonomy the finding has a class of its own. CWE-200 describes a product exposing sensitive information to an actor that is not explicitly authorised to access it (MITRE CWE). The information types listed there include system status and environment such as the operating system and installed packages - precisely what a version banner delivers without a detour. The classification is deliberately broad: it describes no exploitable hole but the stage before one. For internal assessment that difference is useful, because it determines the urgency the item is treated with.
How widespread the disclosure is
The Web Almanac evaluates responses from millions of hosts and has tracked informational headers across several editions. For 2025: these headers show up on 91.5 percent and 23.9 percent of hosts on the web (Web Almanac 2025) - meaning Server and X-Powered-By. Across three editions the curve points slightly downwards, but the movement is small. The report also gives the reason: many web technologies set some of these headers automatically, and the security gain from removing them appears small (Web Almanac 2025). The overview below sorts the fields by what they reveal about the stack behind them.
| Header | Typical content | Prevalence 2025 | What it reveals |
|---|---|---|---|
| Server | Apache/2.4.52 (Ubuntu) | 91.5 percent of hosts | product, usually version, often the distribution |
| X-Powered-By | PHP/7.4.33 | 23.9 percent of hosts | runtime including its version level |
| X-AspNet-Version | 4.0.30319 | far less common | framework version |
| X-Server, X-Backend-Server | web-03.internal | far less common | internal naming scheme, number of nodes |
| Via, X-Cache | 1.1 proxy-01, HIT | varies | upstream caches and their product |
| Error page without header | footer carrying the product name | independent of the header | names the server when the header stays quiet |
The values themselves are where it gets interesting. Among X-Powered-By entries carrying a concrete version, PHP/7.4.33 leads the field: 9.54 percent on desktop and 9.98 percent on mobile (Web Almanac 2025). Across both data sets more than 27 percent of X-Powered-By headers contain version information (Web Almanac 2025). The 7.4 branch has been unmaintained since 28 November 2022, and 7.4.33 was its final release (PHP Manual). Anyone reading that string in a response knows not only the product but also that no security release has appeared for this branch in years. The manual itself urges an upgrade to a current version, because older versions remain open to vulnerabilities and bugs that have since been fixed (PHP Manual).
A header can be faked, trimmed or replaced by an upstream service - the value on display need not match the version actually running. Its absence proves little either: the testing guide notes that the type of server can be guessed from the ordering of the header fields even when the server information is obscured (OWASP Testing Guide). Concluding from a trimmed header that your environment is no longer identifiable mistakes a hurdle for a wall. For your own inventory that means the header is a pointer for clean-up work, not a measure of security posture.
Why a version string attracts automated sweeps
The Web Almanac justifies the measurement with a sentence that captures the chain of effects well: when websites publish excessive information about their infrastructure, such as the server and its specific version, they may run a higher risk of being targeted by automatic vulnerability scanners (Web Almanac 2025). Against that stands the sober note in the server documentation that disabling the Server header does nothing at all to make your server more secure (Apache HTTP Server). Together those two statements set a realistic expectation: the benefit lies in the pre-selection, not in protection. Four mechanisms explain why the pre-selection still matters.
A sweep across thousands of addresses first sorts by traits available at no cost. A version number in the header is exactly such a trait: it answers the question of which route fits before the first real probe runs, shifting compute from reconnaissance to attempt.
Between the publication of a vulnerability and the applied update lies a window. Anyone stating the affected version in plain text during that period is on the shortest list. How to follow new entries in an orderly way is covered in the article on vulnerability feeds.
The information rarely sits in a single header. Web server, runtime, application framework and upstream cache each announce themselves separately. Combined they yield a picture of the stack more precise than any single entry - including how many nodes sit behind it.
Misconfiguration is no footnote in the OWASP Top 10:2025: the category moved up from #5 to #2 (OWASP). It bundles 16 weakness classes with 719,084 occurrences in total and 1,375 entries from the vulnerability database (OWASP).
The numbers behind the category are clear: in the analysis of Security Misconfiguration every application tested was found to have some form of misconfiguration, at an average incidence rate of 3.00 percent (OWASP). A version string in a header is the most harmless member of that family - and at the same time the most visible one, because it can be read from outside without any login. Anyone working through the OWASP Top 10:2025 overview finds the category directly behind broken access control, a position rarely skipped in audit reports.
What the standard says - and what it does not promise
The Server header is described in RFC 9110, the standard for HTTP semantics. It contains no demand to drop the header, but it does contain one to keep it short: an origin server should not generate a Server header field containing needlessly fine-grained detail and should limit the addition of subproducts by third parties (RFC 9110). The reasoning follows in the same section: 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 (RFC 9110). The standard thus draws a line between disclosure and over-disclosure - and puts it at the version number.
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.
— RFC 9110, Section 17.12
The second half matters more, because it sets expectations. The Apache HTTP Server documentation is blunter still at the same point: disabling the Server header does nothing at all to make your server more secure (Apache HTTP Server). Neither statement contradicts the advice to trim the banner - they put its value in perspective. The German federal office for information security nonetheless states the requirement for web servers narrowly and without qualification: neither the product name nor the version of the web server in use should be visible from the HTTP information or from displayed error messages (BSI). Between those poles lies the practical answer: trim it, because it costs little, and patch it, because only that shrinks the attack surface.
A trimmed header changes nothing about the version that actually answers. Removing the line while leaving the branch in place lowers visibility and keeps the risk - and makes your own inventory harder, because the stack is now less readable from outside. The order is therefore: first the patch level of the software in use, then the signature, and both documented. How to find outdated building blocks on the page itself is covered in the article on vulnerable JavaScript libraries.
The settings on each layer
The defaults speak for themselves. On the Apache HTTP Server the default for the ServerTokens directive is simply Full (Apache HTTP Server) - the response then names product, version, operating system type and compiled-in modules in a single line. On nginx, server_tokens defaults to on (nginx); the directive enables or disables emitting the nginx version on error pages and in the Server response header field (nginx). And PHP sets expose_php to 1 by default, which exposes to the world that PHP is installed on the server, including the PHP version within the HTTP header (PHP Manual). Three defaults, three lines in the response - without anyone having configured them.
| Layer | Setting | Default | Effect |
|---|---|---|---|
| Web server, Apache variant | ServerTokens Prod, ServerSignature Off | ServerTokens Full | response names the product only, error page without signature line |
| Web server, nginx variant | server_tokens off | server_tokens on | version disappears from header and error pages at once |
| PHP runtime | expose_php = Off | expose_php = 1 | X-Powered-By drops entirely, takes effect after a restart |
| Application framework | remove framework headers | framework dependent | X-AspNet-Version, X-Generator and similar disappear |
| Upstream service | overwrite or strip headers | pass through | Via, X-Cache and backend names no longer reach the visitor |
| Error and redirect pages | own pages without product names | the product's default page | the footer no longer names the server |
The order of changes is not arbitrary. An upstream service can add, overwrite or pass through headers unchanged; touching only the origin server may leave you with the same response as before. Hence the simple rule: measure from outside, do not read the configuration file. The response at the public address is the only authority that counts, and it regularly differs from what the repository says. Three calls are enough for the counter-check - one before the change, one against an address that does not exist and one afterwards.
Two points are frequently overlooked. First the error pages: a web server's default page names the product in its footer even when the header has already been trimmed. On the Apache HTTP Server, ServerSignature controls that line; on nginx, server_tokens affects header and error pages at once (nginx). Second, the response types rarely requested by hand: redirects, status 404 and status 500 often come from a different layer than the home page and stay untouched by the change. Both belong in the same check as the header - and they complement the overview of security headers, which covers the opposite direction: what a response should additionally contain.
What stays visible after switching off
An empty Server header does not make an environment unrecognisable. The testing guide names the simplest remaining route: where the server information is obscured, the type of server can be guessed from the ordering of the header fields (OWASP Testing Guide). Beyond that, plenty of traits remain that no switch turns off, because they come from the implementation itself rather than from a configuration line.
- Ordering and spelling of the header fields differ by product and persist even when the values themselves give nothing away.
- Structure of the error pages, wording of status messages and the handling of unusual requests are product specific and hard to normalise.
- Names and structure of session cookies point to the runtime; which attributes belong there anyway is covered in the article on secure session cookies.
- Format of ETag values and the handling of conditional requests follow each server's implementation and can be attributed.
- Behaviour on HTTP/2 and HTTP/3 as well as the order of cipher suites offered in the TLS handshake form another identifying trait.
- Open services beyond the web server announce their own identifiers; an inventory of externally reachable services shows which ones exist.
The honest benefit of a trimmed response fits in one sentence: it takes the cheapest sorting aid away from a broad sweep and forces it to spend more effort or move on. Against a targeted attack on a known target it does little. That is precisely why the measure belongs on the same list as removing unused endpoints and clearing out forgotten files - many small steps that achieve little alone and much together, as long as the versions in use are kept current.
Why the banner comes back
Switching it off is a task of minutes. Keeping it off is a state that has to be maintained. In practice the line returns for six recurring reasons, and in nearly every case nobody notices, because the site keeps working. That is exactly what makes this an item for recurring checks rather than for a project handover list.
- Package upgrade with a new default configuration: the update drops an untouched configuration file next to yours or replaces it. Your customisation ends up as a backup copy in the directory and is no longer read.
- An additional service in front: a new cache or balancing layer sets its own headers and writes Via or X-Cache into the response, even though the origin server has long gone quiet.
- A second virtual host: the change was made in the main section and the new site does not inherit it. The result is two addresses of the same organisation with two different answers.
- New image, old default: rebuilding the container pulls the base image fresh and starts back at the default whenever the change is not part of the build recipe.
- A framework upgrade brings new headers: moving to the next version of an application framework adds fields that did not exist before. How quickly versions succeed each other today is shown in the article on two-week release cycles.
- Rollback after an incident: restoring an older state after an incident brings the old configuration along - and with it the old signature.
Adding the header check to ongoing monitoring
An item that returns without warning and causes no visible outage is the textbook case for a recurring measurement. The check itself is cheap: one request per address, a comparison against the last known state, an alert on deviation. The only expensive part is repeating it by hand. Six steps turn it into a routine you can rely on.
- Record the baseline: note today's value of Server, X-Powered-By, X-AspNet-Version, Via and your own framework headers for every address. Without a baseline there is no deviation later, only a snapshot.
- Cover every address, not just the home page: secondary domains, redirect targets, image services and form endpoints often answer from a different layer. How to close that gap systematically is described in the article on URL inventory coverage.
- Include the response types: besides status 200, redirects, status 404 and status 500 belong in the run, because different layers answer there.
- Define the threshold: decide which change triggers an alert - a version number appearing anew should, a changed cache hit marker should not.
- Set up a route for outside reports: whoever discovers a disclosure needs an address to send it to. The article on security.txt and disclosure routes describes the short path there.
- Feed the finding into the regular review: a recurring security scan keeps the header state next to certificate lifetime, availability and content changes, so deviations surface in the same report.
The effort for that routine is small; the benefit is in the side effect. Recording response headers continuously also reveals a switched runtime, the silent introduction of an upstream service and the return of an older state after an incident. A security measure thus becomes a window onto the actual shape of your environment. Which checks run at which interval and what that costs is shown in the plan overview - header analysis is part of the recurring run rather than a separate line item.
This article draws on RFC 9110 (HTTP Semantics) from the IETF, the Web Almanac 2025 by the HTTP Archive, the OWASP Top 10:2025 and the OWASP Web Security Testing Guide. Additional references are the German BSI IT-Grundschutz compendium with module APP.3.2 Web Server, the Apache HTTP Server documentation, the nginx documentation, the PHP manual including the list of unsupported branches and the CWE-200 weakness classification by MITRE. The figures quoted refer to the state of each publication; configuration details apply to the documented version of the respective product.