Une application Web est, de par son exposition au réseau Internet et à ses utilisateurs, sensible aux questions de sécurité. De plus, la souplesse et les largesses de PHP, couplées à celles du protocole HTTP, peuvent rapidement faire passer votre application pour une grosse passoire.
C’est le cas d’une grande partie des solutions PHP du marché, et malheureusement personne n’y coupe : CMS, galeries photos, outils de statistiques… Voici ce qui va introduire plusieurs posts sur la sécurité. Nous y verrons la plupart des failles de sécurité “classiques” qu’on trouve dans les développements PHP, et comment y remédier de façon efficace.
Une des principales brèches dans la sécurité d’une application PHP réside dans la manière de faire les requêtes SQL en utilisant des paramètres dynamiques. Si la récupération d’articles via un simple “SELECT * FROM article” est sans danger pour la sécurité du système, il n’en est pas de même pour les requêtes mélangeant du SQL et des variables PHP. En détournant habilement les variables de leur but d’origine, il est possible d’obtenir une requête totalement différente de celle initialement écrite. On parle dans ce cas d’injection SQL : on injecte du contenu additionnel dans la question envoyée à la base de données.
Prenons un exemple simple. Vous disposez dans votre base de données d’une table utilisateur avec un champ login et un champ password, et un formulaire avec les deux champs associés. Imaginons la requête suivante écrite en PHP et prête à partir dans une fonction mysql_query() :
$sql = "SELECT * FROM utilisateur WHERE login LIKE '" . $_POST['login'] . "' AND password LIKE '" . $_POST['password'] . "'"; $res = mysql_query($sql);
En imaginant que vous passiez respectivement % et % dans les champs du formulaire, les enregistrements de la table seront renvoyés dans tous les cas. Et si par un malheureux (mais courant) concours de circonstances, le premier enregistrement de la table est l’administrateur, vous voilà dans l’accès restreint avec les pleins pouvoirs ! Alors… que faire ? (cf. Jamais ô grand jamais)
1. Contrôler l’origine des paramètres
Il est important d’utiliser PHP avec l’option register_globals à Off. Cela signifie que vous devez récupérer les paramètres utilisateur avec les superglobales $_GET, $_POST et $_COOKIE, ce qui compartimente l’origine des paramètres.
2. Contrôler le typage et le contenu des paramètres
Pour sécuriser les requêtes, la première solution est d’assainir les paramètres et vérifier que le typage attendu correspond. Pour des valeurs de type chaine (un login par exemple), assainissez avec la fonction mysql_real_escape_string() qui convertira les valeurs frauduleuses (’, %, “, #…) pourqu’il n’y ait pas d’éxécution frauduleuse :
$login = mysql_real_escape_string($_POST['login']);
Pour des valeurs numériques, utilisez le casting pour forcer le typage du paramètre :
$i = (integer)$_GET['i']; $f = (float)$_GET['f'];
3. Utilisez de façon raisonnée le langage SQL
Certaines requêtes sont plus faciles à détourner que d’autres. Dans notre exemple initial, le mot clé LIKE permet l’utilisation de % pour renvoyer n’importe quel enregistrement. Attention à certains mots clés, donc, comme par exemple INTO OUTFILE et FROM INFILE, pour exporter ou importer un fichier.
Enfin petite chose importante : l’authentification est la porte d’entrée de votre application. Ne lésinez pas sur la sécurité de cette fonctionnalité, c’est l’endroit le plus exposé à une attaque !
Commentaires récents