Sécurité PHP : Astuce 6
Ce billet est une traduction du billet "PHP Security Tip #6" que vous pouvez trouver sur la devZone du site de Zend. Je ne suis pas un spécialiste de la traduction, et j'ai appliqué un style peut-être trop personnel, merci de votre compréhension et bonne lecture !
Le sujet de la sécurité des applications en PHP ne couvre pas uniquement l'écriture d'un bon code. La plupart des applications utilisent une base de données d'un certain type. Souvent les vulnérabilités qui affectent l'intégralité d'une application sont créées lors de l'écriture de code SQL. L'astuce d'aujourd'hui vous expose une solution simple que les développeurs pourront mettre en pratique.
Lorsque vous avez affaire à des nombres dans une requête SQL, n'oubliez pas de caster.
(NDT : Le cast est une conversion de type, la traduction française, assez inélégante, est "Transtypage")
Même si vous filtrez vos entrées, une mesure simple est de caster toutes les valeurs numériques du traitement SQL.
Prenez par exemple le code suivant :
$myId = filter_var($_GET['id'], FILTER_VALIDATE_INT);
$sql = 'SELECT * FROM table WHERE id = '.$myId;
Même si vous appliquez les filtres natifs de PHP 5.2, il y a autre chose que vous pouvez rajouter.
Essayez plutôt ça :
$myId = filter_var($_GET['id'], FILTER_VALIDATE_INT);
$sql = 'SELECT * FROM table WHERE id = '.(int)$myId;
Ce dernier cast de la variable en entier enlève tous les doutes à propos de ce qui sera passé à MySQL (NDT : L'auteur a probablement fait involontairement une erreur. Au début de l'article il parlait "de base de données d'un certain type", donc de n'importe quel serveur supportant le SQL, comme Oracle, MySQL, SQL Server ou encore MS Access. Alors qu'ici il fait référence au serveur MySQL, cette astuce s'applique bien sûr à tous les serveurs SQL, puisque la faiblesse vient des requêtes que vous êtes susceptibles de faire, et non une faiblesse du serveur MySQL).
L'exemple précédent est simplifiée au maximum, en situation réelle le code sera plus complexe et la probabilité d'erreurs beaucoup plus grande. En appliquant ce cast pendant la construction du traitement SQL vous ajoutez un niveau de sécurité à votre application.
Commentaires
Tu fais bien de préciser que l'envoi de données vers une BDD équivaut à une sortie, et donc qu'il faut l'échapper.
Filtrer tout ce qui rentre dans PHP, échapper tout ce qui sort (en utilisant les bonnes fonctions).
En ce qui concerne l'extension filter : Oui peu d'hébergeurs sont en PHP 5.2, mais il existe également une classe pour filtrer dans le Zend Framework.
Elle m'intéresse bien cette classe :D
Laissez le vôtre !
Les commentaires pour ce billet sont fermés.
Yep,
Je l'avais vue celle ci d'astuce sur le site de Zend. J'ajouterai quelques remarques supplémentaires
1. Utiliser l'extension "filter" reste dans doute la meilleure solution mais malheureusement elle n'est disponible qu'en PHP 5.2 (comme tu l'as évoqué dans le billet). Combien d'hébergeurs tournent sur PHP 5.2 ? Encore trop peu...
2. Le cast d'un Integer peut aussi se faire au moyen des fonctions settype() et intval()
3. Dans le cas des chaînes de caractères, ne pas oublier à les protéger avec les fonctions d'échappement propres au système de BDD : mysql_real_escape_string(), pg_escape_string(), sqlite_escape_string()...
Remarque pour tous les fanas du SiteDuZero : il est complètement inutile d'appliquer un htmlentities() avant envoi en BDD. Un simple appel de la fonction d'échappement du SGBD (voir point précédent) suffit pour protéger la chaine à envoyer en BDD. En revanche, pour éviter toute faille XSS, il faut penser à protéger les données issues de la bdd avec la fonction htmlspecialchars() lorsqu'elles sont affichées.
++
Hugo.