Sécuriser une application Web développée en PHP

Protéger un développement PHP contre les attaques passe notamment par l'application de certaines règles de configuration. La mise en œuvre d'une stratégie de programmation défensive est un plus.

 Le fichier de configuration PHP

En vue de sécuriser un site Web ou une application développée en PHP, certaines règles simples sont applicables lors de l'étape de configuration de l'environnement d'exécution.

Pour modifier les paramètres de PHP, il suffit d'éditer le fichier php.ini qui se trouve dans /etc/phpX/apache/php.ini en remplaçant le X par 4 ou 5 selon la version de PHP utilisée.

1) Mettre la variable register_globals en off

Quand register_globals est à on, les variables EGPCS (Environnement, GET, POST, Cookie, Server) sont enregistrées comme des variables globales. Ainsi, une URL contenant une variable, par exemple http://www.site.com/index.php?var=test crée une variable $var sans besoin d'autre code. De manière général, il faut éviter au maximum les variables globales et utiliser des flots de données explicites.

2) Limiter l'accès aux répertoires

Le safe mode est le mode de sécurité de PHP. Lorsqu'il est activé, il empêche un script d'accéder à des fichiers situés en dehors du dossier où se trouve le site. La vérification est faite en vérifiant le nom du propriétaire du fichier et celui du script.

Parfois trop restrictive, une vérification sur le nom du groupe peut suffire, en utilisant la directive safe_mod_gid. La variable Open_basedir limite les manipulations aux fichiers situés dans les dossiers spécifiés. Il est également possible de désactiver individuellement des fonctions avec disable_functionsDisable_classes fonctionne de la même manière et permet de désactiver individuellement des classes. 

3) display_error=off et log_errors=on

Désactiver l'affichage des erreurs pour éviter d'afficher des informations aux utilisateurs en mettant la variable display_error en off. Il vaut mieux les inscrire dans un journal d'erreurs avec log_errors=on.

4) magic_quotes_gpc=on

Ce paramètre, lorsqu'il est mis sur on, ajoute le caractère "\" devant les apostrophes, les guillemets et le caractère nul. Il empêche ainsi le système d'interpréter une requête qu'un utilisateur malintentionné aurait saisi dans un formulaire HTML. Cette variable tend aujourd'hui à ne plus être utilisée, au profit de la fonction addslashes() pour les requêtes SQL.

5) Changer le répertoire temporaire des identifiants de session

Les identifiants de session sont enregistrés dans un répertoire temporaire. Par défaut, le paramètre session.save_path vaut /tmp est accessible en lecture à tous. Il est donc plus sécurisé d'indiquer le chemin d'un répertoire situé ailleurs sur le système, et dont les droits auront été limités. De plus, il existe une fonction en PHP pour cripter les mots de passe enregistrés. Cette modification peut aussi se faire à partir du fichier de configuration d'Apache, à l'aide de la variable php_value session.save_path.

6) Activer session.use_only_cookies

Cette variable indique si les identifiants de session doivent être utilisés seulement avec des cookies. Par défaut, cette variable est à 0, elle est désactivée et autorise d'autres modes de lecture, par exemple avec les éléments GET ou POST des requêtes HTTP. En mettant session.use_only_cookies à 1, le système lit les informations d'identifiant uniquement à partir des cookies.

 Renforcer son code avec la programmation défensive

La programmation défensive est un état d'esprit qui consiste à écrire son code de façon à s'attendre au pire. Le fait est que le programmeur peut insérer des fautes non détectées ou des inconsistances. Pour s'en prémunir, il faut prévoir un traitement pour les fautes : soit en ajoutant du code vérifiant l'état du système, soit par un traitement d'erreur classique.

1) L'injection de données

Pour éviter que des données non voulues soient injectées dans le code (requêtes SQL, commandes Shell, cross site scripting), il faut vérifier chaque donnée avant de les passer en paramètres à des fonctions du système. Il s'agit de tester si les variables sont bien du type attendu. Il est aussi conseillé d'initialiser chaque variable.  

2) Journaliser toutes les erreurs

Le journal d'erreur est un bon indicateur pour repérer les attaques. Pour enregistrer toutes les erreurs d'exécution, ajouter la ligne <?php error_reporting(E_ALL); ?> au début de chaque page de code. 

 Prendre garde à l'environnement réseau et d'hébergement

Sur le plan de la plate-forme d'hébergement, il est utile de réaliser certaines actions pour se prémunir des attaques.

Des outils comme les reverse proxy permettent d'écarter certaines requêtes faites sur le site (par exemple une requête demandant un chemin qui n'existe pas). 

Utiliser un pare-feu pour bloquer les connexions sortantes depuis le serveur Web, afin d'éviter l'inclusion de fichiers PHP distants (php include).

Attention aux paramètres de sécurité des serveurs mutualisés. Pour une application manipulant des données sensibles nécessitant un haut niveau de sécurité, un serveur dédié sera plus adapté car la configuration sera totalement personnalisable.