Sur la plupart des services d’hébergement mutualisés actuels, chaque site est indépendant des autres au niveau de l’utilisateur Apache. En effet, lors du déploiement basique d’un serveur web, l’utilisateur sous lequel fonctionne le démon est la plupart du temps « www-data », « nobody » ou « apache ». Cela signifie que si plusieurs sites existent sous la même instance d’Apache, tous utilisent le même utilisateur. Ainsi, si l’un des site s’avère corrompu par un utilisateur malveillant, et qu’un shell est obtenu, alors l’assaillant peut profiter pleinement de tous les droits de l’utilisateur sous lequel tourne le serveur web. Tous les sites s’avèrent donc vulnérables.
Une des techniques la plus répandue est de scinder chaque site d’un hébergement mutualisé via des utilisateurs (Unix) distincts. Cette méthode permet de cloisonner l’exécution des scripts web d’un site à un seul et unique utilisateur, empêchant ainsi que cet utilisateur puisse altérer les autres sites mutualisés.
Cette configuration est à réaliser en amont du déploiement des divers sites. Dans le cas d’une migration d’un environnement déjà en production, des manipulations supplémentaires peuvent être nécessaire (modification des .htaccess etc.).
Deux modules d’Apache permettent de réaliser une telle configuration aisément :
- suEXEC : module permettant d’exécuter des scripts CGI à partir de l’utilisateur propriétaire du dit script.
- suPHP : module permettant d’exécuter des scripts PHP à partir de l’utilisateur propriétaire.
Après l’installation et le déploiement de ces modules de sécurité, la configuration de PHP5 sur le serveur web exploitera le fichier de configuration php.ini CGI.
Dans un premier temps, installer les modules concernés :
root@ubuntu:/# apt-get install apache2-suexec root@ubuntu:/# apt-get install apache2-suexec-custom root@ubuntu:/# apt-get install libapache2-mod-suphp
Pour la configuration de ceux-ci, considérons que tous les sites clients vont se trouver dans « /var/www/<SITE>/ », et que chaque répertoire propre à un site disposera des répertoires « httpdocs » pour le contenu du site en lui même et « log » pour la journalisation.
Modification de « /etc/apache2/suexec/www-data ». On indique le répertoire racine de tous les site dans ce fichier, puis le répertoire contenant les fichiers de chaque site (httpdocs).
root@ubuntu:/var/www/monsite/httpdocs# cat /etc/apache2/suexec/www-data /var/www httpdocs # The first two lines contain the suexec document root and the suexec userdir # suffix. If one of them is disabled by prepending a # character, suexec will # refuse the corresponding type of request. # This config file is only used by the apache2-suexec-custom package. See the # suexec man page included in the package for more details.
Pour la configuration de « suphp », il est nécessaire de connaitre l’uid et le gid minimum d’exécution des scripts web. Il est conseillé d’indiquer ceux de l’utilisateur par défaut « www-data » (33 ou 100 généralement) que l’on peut récupérer via la commande:
root@ubuntu:/# id www-data uid=33(www-data) gid=33(www-data) groupes=33(www-data)
Configuration du fichier « /etc/suphp/suphp.conf » :
[root@[dedix chrooted]:/]$ cat /etc/suphp/suphp.conf [global] ;Path to logfile logfile=/var/log/suphp/suphp.log ;Loglevel loglevel=info ;User Apache is running as webserver_user=www-data ;Path all scripts have to be in docroot=/var/www:${HOME}/httpdocs:/usr/share ;Path to chroot() to before executing script ;chroot=/mychroot ; Security options allow_file_group_writeable=false allow_file_others_writeable=false allow_directory_group_writeable=false allow_directory_others_writeable=false ;Check wheter script is within DOCUMENT_ROOT check_vhost_docroot=false ;Send minor error messages to browser errors_to_browser=false ;PATH environment variable env_path=/bin:/usr/bin ;Umask to set, specify in octal notation umask=0022 ; Minimum UID min_uid=33 ; Minimum GID min_gid=33 [handlers] ;Handler for php-scripts application/x-httpd-suphp='php:/usr/bin/php-cgi' ;Handler for CGI-scripts x-suphp-cgi='execute:!self'
Ajouter les chemins d’accès aux scripts, notamment « /usr/share » s’il y a une installation de phpMyAdmin :
;Path all scripts have to be in docroot=/var/www:${HOME}/httpdocs:/usr/share
Désactiver la vérification des racines des « vhost » :
;Check wheter script is within DOCUMENT_ROOT check_vhost_docroot=false
Enfin, régler convenablement l’uid/gid minimum avec celui du compte « www-data »; ainsi que l’umask par défaut « 0022 ».
Pour laisser la main au module suPHP et suEXEC, la désactivation du module PHP5 est requise. suEXEC exploitera le fichier de configuration « /etc/php5/cgi/php.ini » à l’avenir :
root@ubuntu:/# a2dismod php5 root@ubuntu:/# a2enmod suexec root@ubuntu:/# a2enmod suphp
Il ne reste plus qu’à déployer chacun des sites dans « /var/www ». Chaque site nécessite la création d’un nouvel utilisateur/groupe/home qui lui est propre ! Ainsi « /var/www/ » ne doit pas déjà contenir de répertoire pour un site.
root@ubuntu:/var/www# useradd --home /var/www/monsite/ --create-home monsite root@ubuntu:/var/www# mkdir -p monsite/httpdocs root@ubuntu:/var/www# mkdir -p monsite/log
A noter que vous pouvez ajouter un mot de passe pour chaque compte de site (utile pour avoir un serveur FTP par site qui pointe dans son $HOME respectif). Pour définir le mot de passe de chaque compte, utiliser la commande « passwd » ou automatiser la définition du mot de passe via l’attribut « -p » de la commande « useradd » (nécessite un hachage md5-unix, qui peut être créé via le paquet « makepasswd« ).
Créer un fichier de test dans « /var/www/monsite/httpdocs/index.php » contenant la vérification de l’utilisateur d’exécution courante :
<?php system('/usr/bin/id'); echo '<br />'; system('/usr/bin/whoami'); echo '<br />'; phpinfo(); ?>
Ne pas oublier que tous les fichiers/dossiers d’un site protégé par suEXEC et suPHP doivent être la propriété du seul utilisateur Unix autorisé à exploiter le site précédemment créé. Ainsi, redéfinir le chown :
root@ubuntu:/var/www# chown -R monsite:monsite monsite/
Pour finir, il faut indiquer à Apache2 que tel site doit fonctionner sous tel utilisateur. Pour cela, c’est dans les fichiers des « vhosts » qu’une nouvelle directive fait son apparition :
root@ubuntu:/etc/apache2/sites-available# cat monsite <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/monsite/httpdocs ServerName www.monsite.fr ServerAlias monsite.fr SuexecUserGroup monsite monsite <Directory /> Options FollowSymLinks AllowOverride All </Directory> ErrorLog /var/www/monsite/log/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/www/monsite/log/access.log combined </VirtualHost>
Il est conseillé dans ce fichier « vhost » de rediriger la journalisation vers le répertoire « log » précédemment créé pour le site en question. Indiquer le nom du site, les bons alias, le répertoire racine et la directive suEXEC qui précise l’utilisateur et le groupe propriétaire du site :
SuexecUserGroup monsite monsite
Activation du nouveau site (vhost) :
root@ubuntu:/etc/apache2/sites-available# a2ensite monsite
Enfin, redémarrage d’Apache avec toute la nouvelle configuration des modules :
root@ubuntu:/# /etc/init.d/apache2 stop Stopping web server: apache2. root@ubuntu:/# /etc/init.d/apache2 start Starting web server: apache2.
Vérification de la bonne configuration :
On constate que le script « index.php » créé tout à l’heure s’exécute bien. La commande « /usr/bin/id » retourne bien « monsite » ainsi que le « whoami » pour le compte d’exécution courant. La configuration de PHP5 est à présent gérée en mode CGI. Chaque site est à présent scindé par le biais de son utilisateur propriétaire défini dans son fichier vhost.
Dans le cas d’une erreur interne au serveur (erreur 500), vérifier le propriétaire des scripts vis-à-vis du compte défini dans le fichier vhost.
Ce mécanisme est très simple à mettre en oeuvre et permet d’apporter une sécurité notable à un environnement web complet. Couplé à un serveur FTP type « vsFTPd« , chaque site est administrable via FTP en connaissance du nom d’utilisateur/mot de passe propre à chaque site.