Hide your Web stack
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).
##Tools
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.
Section intitulée anonymize-symfony2Anonymize Symfony2
Section intitulée skipping-the-obviousSkipping 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…
Section intitulée the-default-web-assetsThe 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.
Section intitulée our-own-public-assetsOur own public assets
Let’s say our AcmeDemoBundle has a few assets on its own: a demo.css and a main.js files.
If we don’t use Assetic, our main.js file may be included like this:
<script src="{{ asset('/bundles/acmedemo/js/main.js') }}" type="text/javascript"></script>
effectively displaying:
<script src="/bundles/acmedemo/js/main.js" type="text/javascript"></script>
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 *.css files).
With this syntax, all of our *.js files are combined and served from the standard URL /js/main.js:
{% javascripts '@AcmeDemoBundle/Resources/public/js/*' output='js/main.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
We can do the same for *.css files.
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.
With Apache:
RewriteRule ^/media /bundles
With nginx:
rewrite ^/media/(.*)$ /bundles/$1 last;
Section intitulée make-php-keep-a-low-profileMake PHP keep a low profile
Section intitulée change-the-default-cookie-nameChange 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
Section intitulée remove-unnecessary-http-headersRemove unnecessary HTTP headers
PHP advertises itself through the HTTP header X-Powered-By, we can change that by adding
expose_php = off
to our php.ini config file.
Section intitulée hide-app-phpHide app.php
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 /app.php directly.
Section intitulée keep-apache-or-nginx-quietKeep Apache or nginx quiet
Section intitulée remove-unnecessary-http-headersRemove unnecessary HTTP headers
Nginx advertises its name and version with the HTTP header Server. You can remove the version with:
server_tokens off
in the 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 /etc/apache2/conf.d/security file:
ServerTokens Prod
With Apache, there even is a module, mod_security that allows us to set the Server header to anything we want through the SecServerSignature option.
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.
Section intitulée customize-error-pagesCustomize 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 ServerSignature to 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.
##nConclusion
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.
Commentaires et discussions
Ces clients ont profité de notre expertise
Nous avons accompagné Paris Dauphine dans la conception d’une application Symfony2 permettant la gestion complète de trois masters de l’université. Notre intervention a porté sur la conception de l’application, son architecture, et l’aide au développement, par les équipes de l’Université Paris Dauphine, de l’application.
Canal+ a sollicité l’expertise technique de JoliCode dans le cadre d’un audit technique du framework PHP employé par l’entreprise pour ses développements. À l’aide de notre outillage projet, nous avons évalué la qualité du framework et son adéquation avec l’écosystème PHP actuel, et émis une série de recommandations en vue de la modernisation du socle…
À l’occasion de la 12e édition du concours Europan Europe, JoliCode a conçu la plateforme technique du concours. Ce site permet la présentation des différents sites pour lesquels il y a un appel à projets, et encadre le processus de recueil des projets soumis par des milliers d’architectes candidats. L’application gère également toute la partie post-concours…