Protéger un serveur web Apache2 avec suEXEC et suPHP

25
Nov
2012
  • Google Plus
  • LinkedIn
  • Viadeo
Posted by: Yann C.  /   Category: Network and system administration / OS   /   7 Comments

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 :

[bash]</p><br />
<p>root@ubuntu:/# apt-get install apache2-suexec<br /><br />
root@ubuntu:/# apt-get install apache2-suexec-custom<br /><br />
root@ubuntu:/# apt-get install libapache2-mod-suphp</p><br />
<p>[/bash]

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).

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/var/www/monsite/httpdocs# cat /etc/apache2/suexec/www-data&amp;lt;br /&amp;gt;&lt;br /&gt;
/var/www&amp;lt;br /&amp;gt;&lt;br /&gt;
httpdocs&amp;lt;br /&amp;gt;&lt;br /&gt;
# The first two lines contain the suexec document root and the suexec userdir&amp;lt;br /&amp;gt;&lt;br /&gt;
# suffix. If one of them is disabled by prepending a # character, suexec will&amp;lt;br /&amp;gt;&lt;br /&gt;
# refuse the corresponding type of request.&amp;lt;br /&amp;gt;&lt;br /&gt;
# This config file is only used by the apache2-suexec-custom package. See the&amp;lt;br /&amp;gt;&lt;br /&gt;
# suexec man page included in the package for more details.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

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:

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/# id www-data&amp;lt;br /&amp;gt;&lt;br /&gt;
uid=33(www-data) gid=33(www-data) groupes=33(www-data)&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

Configuration du fichier “/etc/suphp/suphp.conf” :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[root@[dedix chrooted]:/]$ cat /etc/suphp/suphp.conf&amp;lt;br /&amp;gt;&lt;br /&gt;
[global]&amp;lt;br /&amp;gt;&lt;br /&gt;
;Path to logfile&amp;lt;br /&amp;gt;&lt;br /&gt;
logfile=/var/log/suphp/suphp.log&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Loglevel&amp;lt;br /&amp;gt;&lt;br /&gt;
loglevel=info&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;User Apache is running as&amp;lt;br /&amp;gt;&lt;br /&gt;
webserver_user=www-data&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Path all scripts have to be in&amp;lt;br /&amp;gt;&lt;br /&gt;
docroot=/var/www:${HOME}/httpdocs:/usr/share&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Path to chroot() to before executing script&amp;lt;br /&amp;gt;&lt;br /&gt;
;chroot=/mychroot&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;; Security options&amp;lt;br /&amp;gt;&lt;br /&gt;
allow_file_group_writeable=false&amp;lt;br /&amp;gt;&lt;br /&gt;
allow_file_others_writeable=false&amp;lt;br /&amp;gt;&lt;br /&gt;
allow_directory_group_writeable=false&amp;lt;br /&amp;gt;&lt;br /&gt;
allow_directory_others_writeable=false&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Check wheter script is within DOCUMENT_ROOT&amp;lt;br /&amp;gt;&lt;br /&gt;
check_vhost_docroot=false&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Send minor error messages to browser&amp;lt;br /&amp;gt;&lt;br /&gt;
errors_to_browser=false&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;PATH environment variable&amp;lt;br /&amp;gt;&lt;br /&gt;
env_path=/bin:/usr/bin&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Umask to set, specify in octal notation&amp;lt;br /&amp;gt;&lt;br /&gt;
umask=0022&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;; Minimum UID&amp;lt;br /&amp;gt;&lt;br /&gt;
min_uid=33&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;; Minimum GID&amp;lt;br /&amp;gt;&lt;br /&gt;
min_gid=33&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[handlers]&amp;lt;br /&amp;gt;&lt;br /&gt;
;Handler for php-scripts&amp;lt;br /&amp;gt;&lt;br /&gt;
application/x-httpd-suphp=&amp;amp;quot;php:/usr/bin/php-cgi&amp;amp;quot;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Handler for CGI-scripts&amp;lt;br /&amp;gt;&lt;br /&gt;
x-suphp-cgi=&amp;amp;quot;execute:!self&amp;amp;quot;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

Ajouter les chemins d’accès aux scripts, notamment “/usr/share” s’il y a une installation de phpMyAdmin :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Path all scripts have to be in&amp;lt;br /&amp;gt;&lt;br /&gt;
docroot=/var/www:${HOME}/httpdocs:/usr/share&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

Désactiver la vérification des racines des “vhost” :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;;Check wheter script is within DOCUMENT_ROOT&amp;lt;br /&amp;gt;&lt;br /&gt;
check_vhost_docroot=false&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

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 :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/# a2dismod php5&amp;lt;br /&amp;gt;&lt;br /&gt;
root@ubuntu:/# a2enmod suexec&amp;lt;br /&amp;gt;&lt;br /&gt;
root@ubuntu:/# a2enmod suphp&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

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.

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/var/www# useradd –home /var/www/monsite/ –create-home monsite&amp;lt;br /&amp;gt;&lt;br /&gt;
root@ubuntu:/var/www# mkdir -p monsite/httpdocs&amp;lt;br /&amp;gt;&lt;br /&gt;
root@ubuntu:/var/www# mkdir -p monsite/log&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

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]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;amp;lt;?php&amp;lt;br /&amp;gt;&lt;br /&gt;
system(&amp;amp;quot;/usr/bin/id&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
echo &amp;amp;quot;&amp;amp;lt;br /&amp;amp;gt;&amp;amp;quot;;&amp;lt;br /&amp;gt;&lt;br /&gt;
system(&amp;amp;quot;/usr/bin/whoami&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
echo &amp;amp;quot;&amp;amp;lt;br /&amp;amp;gt;&amp;amp;quot;;&amp;lt;br /&amp;gt;&lt;br /&gt;
phpinfo();&amp;lt;br /&amp;gt;&lt;br /&gt;
?&amp;amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/php]

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 :

[bash]root@ubuntu:/var/www# chown -R monsite:monsite monsite/[/bash]

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 :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/etc/apache2/sites-available# cat monsite&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;lt;VirtualHost *:80&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
ServerAdmin webmaster@localhost&amp;lt;br /&amp;gt;&lt;br /&gt;
DocumentRoot /var/www/monsite/httpdocs&amp;lt;br /&amp;gt;&lt;br /&gt;
ServerName www.monsite.fr&amp;lt;br /&amp;gt;&lt;br /&gt;
ServerAlias monsite.fr&amp;lt;br /&amp;gt;&lt;br /&gt;
SuexecUserGroup monsite monsite&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;lt;Directory /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Options FollowSymLinks&amp;lt;br /&amp;gt;&lt;br /&gt;
AllowOverride All&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;lt;/Directory&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
ErrorLog /var/www/monsite/log/error.log&amp;lt;br /&amp;gt;&lt;br /&gt;
# Possible values include: debug, info, notice, warn, error, crit,&amp;lt;br /&amp;gt;&lt;br /&gt;
# alert, emerg.&amp;lt;br /&amp;gt;&lt;br /&gt;
LogLevel warn&amp;lt;br /&amp;gt;&lt;br /&gt;
CustomLog /var/www/monsite/log/access.log combined&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;lt;/VirtualHost&amp;amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

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 :

[bash]SuexecUserGroup monsite monsite[/bash]

Activation du nouveau site (vhost) :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/etc/apache2/sites-available# a2ensite monsite&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

Enfin, redémarrage d’Apache avec toute la nouvelle configuration des modules :

[bash]&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;root@ubuntu:/# /etc/init.d/apache2 stop&amp;lt;br /&amp;gt;&lt;br /&gt;
Stopping web server: apache2.&amp;lt;br /&amp;gt;&lt;br /&gt;
root@ubuntu:/# /etc/init.d/apache2 start&amp;lt;br /&amp;gt;&lt;br /&gt;
Starting web server: apache2.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;[/bash]

Vérification de la bonne configuration :

Vérification du fonctionnement de suEXEC et suPHP

Vérification du fonctionnement de suEXEC et suPHP

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.

  • Google Plus
  • LinkedIn
  • Viadeo
Author Avatar

About the Author : Yann C.

Consultant en sécurité informatique et s’exerçant dans ce domaine depuis le début des années 2000 en autodidacte par passion, plaisir et perspectives, il maintient le portail ASafety pour présenter des articles, des projets personnels, des recherches et développements, ainsi que des « advisory » de vulnérabilités décelées notamment au cours de pentest.