How it works
With every answer the server sends headers the browser does not need. Server: Apache/2.4.57 (Debian) says which web server runs in which version, X-Powered-By: PHP/8.1.2 does the same for the programming language. X-AspNet-Version, X-AspNetMvc-Version and X-Generator, which some CMSs fill with their name, give similar details.
For known versions there are public lists of vulnerabilities. Automated scanners read the headers and try exactly the attacks that fit that version. The details save them the search.
What matters
- No version numbers.
Server: nginxwithout a version is harmless; it is the number that reveals which holes might be open. - Remove the extra headers entirely. No browser needs
X-Powered-By,X-AspNet-Version,X-AspNetMvc-VersionorX-Generator, with or without a version. - Hiding is no substitute for updates. Removing the version makes life harder for scanners but closes no hole. Keep server, CMS and plugins up to date.
- Check every layer. Web server, programming language, CMS and a proxy in front can each add details of their own.
How to set it up
Whoever runs the server switches the details off: you, your agency or the hosting provider. The main places:
For PHP, in php.ini:
expose_php = Off
In ASP.NET, <httpRuntime enableVersionHeader="false" /> in web.config removes the X-AspNet-Version header; X-Powered-By is removed in IIS's response headers. In Express (Node.js), app.disable("x-powered-by") switches the header off.
Other headers can be filtered out in the web server, with Header unset X-Generator in Apache, or with fastcgi_hide_header X-Generator; in nginx in front of PHP-FPM. On shared hosting without access to the configuration, ask your hosting provider.