JeuWeb - Crée ton jeu par navigateur
Se protéger contre l'injection SQL - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Se protéger contre l'injection SQL (/showthread.php?tid=3277)

Pages : 1 2 3


Se protéger contre l'injection SQL - Kassak - 20-11-2008

Bonjour bonjour, je suis en train de voir comment réduire au maximum les risques d'injection SQL sur mes formulaires.

Pour le moment, j'utilise les solutions suivantes :

-Nom de table plus compliqué, du style tdk_membre...
-Vérifier après récupération d'une données en GET si elle ne contient bien que des chiffres, ou que des lettres, minuscule ou majuscule..sinon on quitte la page.
-Après qu'un membre est validé un formulaire, on récupère les données des champs, et on utilise un petit mysql_real_escape_string($_POST['xx']) afin de vire les caractères généralement utilisé en cas d'injection.


Mais ensuite, que peut on faire de plus ?


Edit : Il y a bien des tutos sur le net, mais comme toujours, je préfère entendre VOS solutions Wink


RE: Se protéger contre l'injection SQL - Sephi-Chan - 20-11-2008

Plus simplement, pour éviter les injections, il suffit de contrôler les données qui entrent dans le programme. Pour ça, il faut écrire des validateurs (c'est une force des frameworks, qui proposent d'excellentes solutions de ce genre) qui vérifient le format des données. Donc, si c'est un identifiant correct (is_numeric($var) === true && $var > 0), mais également des regex pour les chaînes, etc. Si tu attends une valeur dans une liste, tu vérifies que la valeur reçue est bien dans la liste, etc.

Bref, les données entrées doivent être fiables : ce sont celles que tu attends et rien d'autre.

Ensuite, tu échappes avec la fonction de ton SGBDR (mysql_real_escape_string() pour MySQL, effectivement) les chaînes de caractères (ça ne sert à rien d'échapper un nombre ^^).

Le problème, c'est qu'on a beau le savoir, on en oublie forcément quelque part. :heuuu:


Sephi-Chan


RE: Se protéger contre l'injection SQL - phenix - 20-11-2008

Au risque de répéter ce qui a déjà été dit, mais la solution la plus simple est d'appliquer mysql_real_escape_string() sur les donne POST et GET qui sont envoyer et qui seront utilisé pour faire des requêtes.

Si tu as la flemme tu peux utiliser un truc genre array_walk($_POST, 'mysql_real_escape_string'); mais perso j'ai pas tester si sa marchait...


RE: Se protéger contre l'injection SQL - Kassak - 20-11-2008

J'ai pas trop pigé l'histoire des validateurs Sephi...

Phenix, array_walk sert à quoi ?


KassaK, qui n'a rien compris....


RE: Se protéger contre l'injection SQL - Sephi-Chan - 20-11-2008

Kassak a écrit :J'ai pas trop pigé l'histoire des validateurs Sephi...
Et bien il te suffit d'écrire une fonction qui valide (ou non) tes variables. Une fonction a qui tu donnes une valeur et qui te renvoie true si cette valeur est valide, et false si elle ne l'est pas. Par exemple isValidNickname(), isValidId(), etc.

Kassak a écrit :Phenix, array_walk sert à quoi ?
Sans être Phenix, je peux dire que tu déconnes… Il te suffit de taper l'URL php.net/array_walk pour le savoir.

Par contre, je te déconseille fortement cette méthode puisque c'est du gâchis. Tout n'a pas à être échappé. La sécurité, ça se fait de manière intelligente, pas comme un bœuf !?

Si tu es curieux, tu peux consulter la documentation des composants Zend Validate, Zend Filter du Zend Framework. C'est extrêmement souple.
Et si tu aimes bidouiller et ne pas réinventer la roue, tu peux même songer à utiliser ces classes dans ton application ! Pourquoi pas en complément de Zend Form ?


Sephi-Chan


RE: Se protéger contre l'injection SQL - Kassak - 20-11-2008

Ok, je vais voir tout ça merci bien Wink

Et pour le array_walk, faut dire que j'avais la flemme de chercher -_-'.


RE: Se protéger contre l'injection SQL - Ekilio - 20-11-2008

Pour ceux qui ne voudrais pas s'embetter avec tout le Zend Framework, il y a aussi filter_var qui est interessant...


RE: Se protéger contre l'injection SQL - Ter Rowan - 20-11-2008

pour bien préciser :p

1) mysql_real_escape_string() suffit si je veux utiliser une saisie utilisateur (venant du poste client quoi) dans une requête SQL (que ce soit de l'update, de l'insert, du select)

2) est-il utile de toujours tester le "is_numeric" , dans le cas où la valeur 0 ne pose pas un risque (ie si =0 alors pas d'action)

ie. que se passe t il si
- toto = 3* $Post["toto"]; (avec "13aaaieri" ou "aeeer")

est ce que le résultat est : toto = 39 et toto = 0

- "Select * from truc where id =".mysql_real_escape_string($Post["toto"])
avec toto "aeee OR 1=1"

est ce que le résultat est : "Select * from truc where id =0" ou "Select * from truc where id = 0 OR 1=1"


RE: Se protéger contre l'injection SQL - Ekilio - 20-11-2008

Ter Rowan a écrit :pour bien préciser :p

1) mysql_real_escape_string() suffit si je veux utiliser une saisie utilisateur (venant du poste client quoi) dans une requête SQL (que ce soit de l'update, de l'insert, du select)

2) est-il utile de toujours tester le "is_numeric" , dans le cas où la valeur 0 ne pose pas un risque (ie si =0 alors pas d'action)

ie. que se passe t il si
- toto = 3* $Post["toto"]; (avec "13aaaieri" ou "aeeer")

est ce que le résultat est : toto = 39 et toto = 0

Le resultat est simple à voir :
Code PHP :
<?php
$a
= 3;
$b = '13aaaieri';
echo
$a * $b;
?>

Cela donnera 39. Ce résultat est lié à la une chose amusante nommée le transtypage, qui est la conversion automatique d'une variable en fonction du type. Je ferais un tuto sur ça si vous voulez, c'est assez interessant à étudier les types en PHP.

Citation :- "Select * from truc where id =".mysql_real_escape_string($Post["toto"])
avec toto "aeee OR 1=1"

est ce que le résultat est : "Select * from truc where id =0" ou "Select * from truc where id = 0 OR 1=1"

Le résultat est "Select * from truc where id = 0 OR 1=1". mysql_real_escape_string ne fait qu'ajouter des antislash (\) devant les caractères que le serveur MySQL doit échapper (en gros, les guillemets et autres choses du même acabit). Ce n'est en aucun cas une filtration de type !

Pour faire de manière sécurisée, il faut utiliser is_numeric ou (plus simple) intval. J'utilise en général intval que je trouve beaucoup plus pratique puisque ça me permet de traiter ma requête sans tests :

"Select * from truc where id =".intval($Post["toto"])

Ceci donnera :

Select * from truc where id = 0

Bon, je vais vous faire un bon gros tuto sur le typage strict en php et comment l'utiliser...

Edit : Après la réponse de Sephi-Chan et un benchmark, (int) est plus adapté que intval() car il donne de meilleurs performances.


RE: Se protéger contre l'injection SQL - Sephi-Chan - 20-11-2008

Dans ce cas, plutôt que d'utiliser intval, n'est-il pas encore plus simple de faire un transtypage (cast) ? Par exemple :
Code PHP :
<?php 
'SELECT * FROM table WHERE id = ' . (int) $id

Dans tous les cas, ce n'est pas une approche que je cautionne car à mon sens, une application doit s'arrêter lors d'un cas particulier.

A mon sens, si l'identifiant attendu n'est pas valide (à savoir un entier positif), l'application doit renvoyer une exception, et ne surtout pas utiliser une donnée que l'on ne maîtrise pas. Dans l'exemple, ça donne lieu à une requête SQL inutile (du gâchis, donc).

C'est également ce que nous a enseigné notre professeur de C l'an dernier. Et c'est le genre de personne qui a derrière lui une longue et impressionnante carrière, je lui fais donc confiance.


Sephi-Chan