Hiding your web stack may be very useful to discourage most of the malicious users to try to do harm on your website. We’re going to list a few measures we can take to hide these informations from a malicious user who could take advantage of them.
Let’s say we’re running a website using Symfony2 on a classic LAMP/LEMP stack (the “E” is for (e)nginx). We’re going to use the Symfony2 Standard Edition with the AcmeDemoBundle unremoved (and loaded even in production) as an application example.
We’ll go from the top (the Symfony framework) to the bottom (our web server).
There is a good Chrome Extension called Wappalyzer that can gather indications from a page URL, header’s, etc… to tell which technologies it’s using. It may be helpful to measure the progress our app is making through complete anonymousness.
Skipping the obvious
Change the default favicon, do not deploy the
app_dev.php nor the
config.php in production, customize error 404 and 50x pages…
The default web assets
Public assets packaged with the application, like the stylesheets and the images used by the Web Debug Toolbar are of no use in production and shouldn’t be deployed.
Accessing a particular file like
/bundles/framework/css/exception.css which has a rich history on Github could help determine the version of Symfony2 used by our application.
We can either configure our webserver to serve 404 pages for URLs starting with /bundles (if we use Assetic, see below) or choose to not deploy them.
Our own public assets
Let’s say our AcmeDemoBundle has a few assets on its own: a
demo.css and a
If we don’t use Assetic, our
main.js file may be included like this:
The use of the folder hierarchy
/bundles/bundlename/js/... is pretty characteristic of the Symfony2 framework (and may also leak infos about the logical organization of your application).
The best way to avoid this is to use Assetic which allows us to compile a list of
*.js into one (idem for
With this syntax, all of our
*.js files are combined and served from the standard URL
We can do the same for
There is no easy way to do the same with images: the
AssetsInstallCommand hardcodes the prefix url to
/bundles/acmedemo. It uses the
Bundle::getName() method which is final, meaning we can’t override the “acmedemo” part.
If we have access to our webserver config, we can rewrite the
/bundles part in
/media for instance.
RewriteRule ^/media /bundles
rewrite ^/media/(.*)$ /bundles/$1 last;
Make PHP keep a low profile
Change the default cookie name
By default the cookie is named
PHPSESSID. We can change that by editing the config.yml file like this:
framework: session: name: acmedemo
Remove unnecessary HTTP headers
PHP advertises itself through the HTTP header
X-Powered-By, we can change that by adding
expose_php = off
php.ini config file.
In most configurations, even if
/ is rewritten into
/app.php, we can still access
/app.php directly. Most frameworks name their front controller
index.php so this could be a good indication that our app is running Symfony2. We could rename
app.php or if we want to completely hide the fact that we’re running PHP, we need to tell Apache or nginx to serve a 404 if someone access
Keep Apache or nginx quiet
Remove unnecessary HTTP headers
Nginx advertises its name and version with the HTTP header Server. You can remove the version with:
nginx.conf file but if it’s not enough for you, you can modify the sources and recompile nginx to get rid of the remaininx “nginx” string as described here.
The same modification can be achieved with Apache by setting the following directive in the
With Apache, there even is a module, mod_security that allows us to set the Server header to anything we want through the
Another way to achieve this would be to install a reverse-proxy like Varnish that allows you to manipulate headers freely and the server signature in particular.
Customize error pages
Error pages are a simple way when not customized to detect the webserver in use.
You can either remove sensitive informations by setting
off in the
/etc/apache2/conf.d/security file or make apache serve custom 404 and 50x pages.
With nginx, setting
server_tokens to off hides nginx version in all visible places.
At the end of day, a webserver is what it is and there may be no easy way to absolutely hide its nature from malicious users but this is where hackers often start and these measures can be a good starting point to harden your web app.