Sécuriser un serveur Apache avec PHP : suPHP

suphp_logoCe billet fait suite aux précédents billets sur le sujet de la sécurisation d’Apache avec PHP à savoir la problématique et un premier élément de réponse. Pour résumer rapidement, nous avons vu les problèmes que posait une installation par défaut d’Apache supportant le PHP dans le cas d’un serveur web mutualisé tel qu’on pourrait le trouver chez un hébergeur. Nous avons ensuite vu comment la configuration PHP pouvait influer sur la sécurité de l’installation.  Dans ce billet, nous allons voir la configuration et l’utilisation de suPHP.

Objectif

J’avais parlé de la problématique des droits avec lesquels s’exécutent les scripts PHP ainsi que du fait qu’il n’y ait qu’un seul fichier de configuration PHP pour tous les sites présents sur une même machine. Le module Apache dénommé suPHP va permettre de répondre à ces deux problématiques et de rajouter même quelques fonctionnalités supplémentaires. Si on va sur leur site, on se rend bien compte que l’objectif de suPHP est d’exécuter les scripts PHP avec les droits du propriétaire du script. Ceci va nous permettre d’attribuer un utilisateur par site et donc d’obtenir un meilleur cloisonnement. Nous verrons par la suite plus en détail la configuration et les possibilités offertes par suPHP.

Installation de suPHP

Sur une distribution de type Debian, l’installation se fait via le gestionnaire de paquet traditionnel apt-get.

# apt-get install libapache2-mod-suphp

# a2enmod suphp

Sur les autres distributions, vous pourrez soit passer par le gestionnaire de paquet soit par la compilation à la main. Comme pour tous les modules Apache, la compilation à la main est très simple et efficace. Il ne faut juste pas oublier de déclarer le module dans le fichier de configuration d’Apache.

Configuration de suPHP

Une fois que vous avez installé suPHP, vous n’avez finalement pas rajouté beaucoup de sécurité dans votre installation. Il va falloir s’atteler à la configuration. La première étape de la configuration est de s’assurer que chaque site ait son propre utilisateur. Sans cette mesure, suPHP est largement moins efficace. On va ensuite étudier le fichier de configuration de suPHP qui se trouve dans /etc/suphp/suphp.conf.

;Path all scripts have to be in
docroot=/data/www

Cette directive vous permet de configurer le répertoire dans lequel suPHP aura le droit d’exécuter des scripts PHP. Les scripts en dehors de ce répertoire ne seront pas exécutés et le serveur web affichera une erreur 500 (Internal Server Error).

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

Ce jeu de directives va vous permettre d’autoriser ou non vos utilisateurs à mettre des droits très élargis à leur fichiers. Par exemple, si vous activez la première directive, suPHP refusera d’exécuter les scripts PHP qui permettent l’écriture par le groupe du propriétaire du fichier. A vous de voir si vous voulez implémenter ce type de restrictions. Je ne trouve pas ca très utile si vous avez bien réglé la directive PHP open_basedir.

; Minimum UID
min_uid=100
; Minimum GID
min_gid=100

Ce jeu de directives vous permet de paramétrer l’UID et le GID minimal avec lequel peuvent être exécutés des scripts PHP.  Ceci va vous permettre d’éviter que des scripts soient exécutés avec l’utilisateur www-data voire root. Il existe d’autres lignes de configuration que je n’ai pas explicitées ici. Je vous invite à consulter la documentation pour en savoir plus.

Configuration du VirtualHost

Une fois que nous avons correctement configuré suPHP, il n’est toujours pas actif. Il va falloir l’activer au cas par cas en fonction du VirtualHost. Ceci permet d’avoir une meilleur finesse de réglage quant à l’activation de ce module. Rien de plus simple pour l’activer il suffit de rajouter la ligne suivante dans le VirtualHost.

suPHP_Engine On

On va pouvoir ensuite rajouter plusieurs réglages fournis par suPHP afin d’implémenter plus de sécurité et de flexibilité. Comme je vous en avais parlé précédemment, il va être possible d’attribuer un fichier php.ini par VirtualHost. Il est essentiel que vos clients ne puissent pas modifier ce php.ini directement. Si cela est possible, il sera possible à n’importe qui de modifier la directive open_basedir supprimant ainsi un niveau de sécurité. On va donc rajouter la directive suivante :

 suPHP_ConfigPath /data/www/********.com/priv/php.ini

Au final, à travers ces trois billets nous avons pu faire un tour d’horizon permettant la sécurisation d’un serveur Apache doté de PHP. Je pense que l’implémentation des fonctionnalités présentées à travers ces trois billets permet d’atteindre un niveau de sécurité correct sur un serveur web mutualisé. Il n’existe bien sûr par de sécurité parfaite. Il faut surtout adopter une hygiène de configuration et de paramétrage en association avec la configuration correcte des modules associés.

Sécuriser un serveur Apache avec PHP : début de solution

apache_logoCe billet fait suite au précédent qui avait pour objectif de vous faire une démonstration des problématiques liées au déploiement d’un serveur web mutualisé basé sur Apache. Je vais donc vous présenter des solutions permettant de résoudre ces problèmes.

Limites

Je n’ai pas la prétention de vous permettre de sécuriser parfaitement un serveur Apache. Je vous présente ici une série d’éléments que j’ai pu apprendre à travers mon précédent emploi. Il faut dire qu’un hack de serveur web toutes les deux semaines, ca force à s’occuper de la sécurité des serveurs web. J’exagère, hélas, à peine.

Ces solutions de sécurisation permettent d’éviter qu’un site puisse nuire aux autres sites sur le serveur web. Si un site mal codé dispose de failles de sécurité rendant possible une attaque sur lui même, je n’ai pas de solution coté serveur à vous proposer. Dans ce cas, il faut se plonger dans le code et réparer les failles de sécurité. Ces solutions permettront tout de même de vous prémunir d’une attaque sur toute votre plateforme et de pouvoir rejeter la faute sur vos clients.

Choix du logiciel PHP

Tout d’abord, lorsque vous installez un serveur web, il est fortement recommandé d’installer la version Suhosin. Il s’agit d’une version de PHP qui a été patchée pour réparer des failles de sécurités connues. La liste des améliorations est disponible sur leur site. Si vous avez fait le choix judicieux de prendre une distribution Debian, les versions de PHP qui sont livrées avec disposent d’office du patch Suhosin. Je ne sais pas ce qu’il est des autres distributions mais je doute que ce soit le cas partout.

Ensuite, il faut avoir une version PHP à jour. Ca parait peut être inutile de dire ca mais ca reste une condition essentielle. La mise à jour des logiciels permet de bénéficier de la réactivité des communautés en termes de mises à jour de sécurité. Ce serait quand même dommage de ne pas en profiter et de se faire compromettre un serveur à cause de failles connues depuis plusieurs mois.

Configuration de PHP

La configuration de PHP peut largement influer sur la sécurité du serveur web. Il existe de nombreuses fonctionnalités de PHP qui permettent de faire des choses intéressantes pour le développeur mais très inquiétant pour l’administrateur système.

Tout d’abord, la directive fopen est une directive qui devrait être désactivée par défaut. Cette directive permet d’ouvrir un fichier et ensuite de le modifier ou bien de le lire. Par défaut, si cette directive est activée, il est possible de lire n’importe quel fichier dont /etc/passwd. « Mais /etc/passwd, tout le monde ne peut pas le lire ! ». Et bien si, les droits sur les fichiers /etc/passwd sont de 644. Le monde entier pourra donc trouver la liste des comptes utilisateurs de votre machine sur le web.

Ensuite, si un de vos clients a besoin de la directive fopen, car elle peut quand même être utile. Vous allez donc devoir restreindre l’accès aux fichiers ce qui est possible dans PHP via la directive open_basedir. Grace à cette directive, vous allez donc contraindre vos clients à ne pas sortir de leur répertoire que ce soit pour l’exécution de scripts PHP ou la modification/lecture de fichiers.. Il est également généralement recommandé de désactiver la directive register_globals mais je ne suis pas capable de justifier pourquoi. Je sais juste qu’il s’agit d’une option qui n’est plus d’actualité dans les versions de PHP d’aujourd’hui (Plus d’informations sur ce site).

Grace à ces éléments, la sécurité de votre serveur web sera déjà bien améliorée. Afin de pouvoir aller encore plus loin et améliorer le niveau de sécurité, je vous présenterais suPHP la prochaine fois.

Sécuriser un serveur Apache avec PHP : la problématique

Logo PHPLe PHP est un langage web qui permet de faire des sites web dynamiques. Ce qui a fait sa popularité c’est sa simplicité d’utilisation dans la mesure où n’importe qui peut donner 10€ à OVH ou à 1&1 et avoir un espace d’hébergement compatible PHP. C’est souvent le langage de programmation sur lequel démarrent beaucoup de programmeurs autodidactes. Quand on lit ca, on peut se dire « Chouette ! C’est cool PHP on peut programmer simplement pleins de trucs trop biens ! Si je m’y mettais ?! ». D’un coté, c’est pas faux, vous allez nous coder un super site tout moche parcque vous savez pas utiliser Photoshop. D’un autre coté, vous allez surement coder un site bourré de failles de sécurité.

Et oui, les sites PHP sont souvent bourrés de faille car les programmeurs débutants n’ont souvent pas de connaissance en programmation sécurisée. Si c’est vous à titre personnel, vous vous ferez démonter votre site perso et vous irez pleurer mais les conséquences ne seront pas dramatiques. Par contre, si vous vous appelez « Web Agency », « Web Designer » ou tout autre appelation d’origine non controlée vous allez venir vous plaindre à votre hébergeur car il n’a pas sécurisé son serveur alors que c’est votre code qui est pourri. Et ca, ca m’énerve.

Après avoir râlé, il faut quand même admettre que l’hébergeur d’un serveur web peut avoir une responsabilité dans la compromission de votre site web. Ce cas de figure n’est valable que sur un serveur mutualisé.

Vous venez donc de monter votre serveur web tout beau tout neuf sur votre serveur dédié. Vous avez l’agréable sensation d’avoir accompli quelque chose vraiment bien, normal. Ce que vous ne ressentez pas c’est le manque de sécurité total de votre installation. Je vous rassure, on ne ressent ce genre de choses que quand c’est bien trop tard.

Problèmes de droits

Par défaut, Apache exécute tous les sites web ou VirtualHosts avec l’utilisateur par défaut, www-data sur les distributions type Debian ou apache sur les distributions type RHEL. Quand je parle d’exécution, je parle de lecture des fichiers HTML (parfaitement anodin) mais aussi d’exécution de scripts PHP. Cela veut dire que tous les sites ont les mêmes droits en lecture et en écriture, quelque chose du genre 775 avec en propriétaire www-data. Si vous avez bien fait le calcul, cela signifie que rien n’empêche un script PHP d’aller lire/modifier/détruire un fichier d’un autre VirtualHost. Normal, ces fichiers ont les mêmes droits.

Avec ce type de configuration par défaut, n’importe quel client peut aller lire les fichiers d’un autre client pour peu qu’il soit un peu futé. Il va pouvoir y lire des lignes de code mais aussi des identifiants SQL par exemple… Qui dit identifiants SQL dit base de données remplie de données. De quoi y faire un vrai festin.

Problèmes de modification de droits

Vous êtes conscients du problème des droits et vous avez donc créé un utilisateur pour chaque site web avec un uid différent bien évidemment (ne rigolez pas c’est du vécu). Le soucis c’est que chaque utilisateur va avoir la possibilité de faire un « chmod » sur tous les fichiers de son site et donc de tout passer en 777, c’est tellement plus simple.Au final, on revient donc à la situation précédente ou n’importe quel site peut lire/modifier/détruire les fichiers des autres sites.

De plus, vu que le serveur web s’exécute toujours en www-data, vous devez donner les droits d’écriture à www-data si vous voulez que le serveur web puisse écrire. Ceci donne également la possibilité à des scripts PHP d’autres sites d’aller jouer avec tous les fichiers qui sont en écriture pour le serveur web.

Un unique fichier de configuration

Ensuite, lorsque vous installez PHP sur votre distribution préférée, vous avez un seul fichier php.ini qui régit par défaut toutes les variables de PHP pour le serveur. Vous vous faites donc une configuration ultra top sécurisée ou alors vous le laissez par défaut, mais on va supposer la première option. Le seul soucis c’est que vu que vous hébergez pleins de clients, vous avez pleins de demandes différents telles que l’activation du fopen ou register_globals qui sont des failles de sécurité ultra connues. Vous refusez de leur activer ? Ils refusent de vous payer, logique. Donc vous l’activez. Et là, c’est le drame, vous l’avez activé pour 200 sites.

Vous l’aurez bien compris, une installation par défaut d’Apache et PHP est très peu sécurisée dans le cas d’utilisation dans le cadre d’un serveur web mutualisé. Je vous présenterais dans la suite des billets les solutions pour répondre à ces problèmes car il en existe, rassurez-vous.