Comment proteger des injections SQL ?

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Comment proteger des injections SQL ?

par seïna » 07 août 2008, 19:12

Euh désolée mais ce n'est pas moi qui ai ouvert la discussion donc je suppose que je ne peux pas la marquer comme résolue. Comme elle concernait la question que je me posais j'ai sauté sur l'occasion. Je me suis d'ailleurs inscrite avant d'envoyer mon premier message.

par albat » 07 août 2008, 13:28

Modération :
Puisque ta question est résolue, j'ajoute le tag [Résolu]
pour indiquer aux personnes qui voudront consulter ce sujet qu'il contient une solution.

Tu peux réaliser cette opération toi-même
en cliquant sur le bouton Image
qui s'affiche en haut à gauche de ce sujet
si tu as posté le 1er message en tant que membre (inscrit et identifié).

Alors... inscris-toi !!! ;)

par Invité » 07 août 2008, 12:01

Franchement merci beaucoup Sékiltoyai pour tes explications très claires et enrichissantes =D>
Je vais appliquer tout ça.

par Sékiltoyai » 07 août 2008, 00:20

En gros après le formulaire tu modifies les données pour qu'elles soient "valides". A savoir que évidemment tu vérifies la validité des champs (bonne formation d'une adresse mail, d'une ip, d'un pseudo). Tu modifies les données au besoin ou demandes modification (selon la politique du site). Par exemple pour un numéro de téléphone tu peux supprimer les espaces, les points, les tirets, si quelqu'un a placé des séparateurs, pour un pseudo, tu peux éventuellement utiliser un trim, etc…

Dans ta base tu as alors les données les plus naturelles possibles, et toutes sous le même format. Si tu dois appliquer un filtre pour nettoyer le numéro de téléphone (pour notre exemple), tu le fais avant, parce que sinon tu te retrouves avec des données totalement hétérogènes, et tu ne peux à aucun moment t'assurer de l'unicité des données, voire faire une recherche correcte.
Le problème est le même lorsque l'on utilise htmlentities. Comment rechercher des caractères accentués dans une table facilement si on a appliqué htmlentities auparavant. htmlentities est clairement une fonction d'affichage puisqu'elle prépare pour un affichage html. Les données ne sont plus valides pour un autre usage. C'est là l'enjeu. Les données doivent être génériques et valables pour n'importe quel usage. Si tu as appliqué une modification avant, tu brides complètement les usages.
Donc tous les urlencode, htmlentities, traduction de bbcode (comment veux tu modifier un post si le bbcode a déjà été traduit en balises html lors du stockage ?), toutes les fonctions d'affichage en bref doivent être réservées à l'affichage.

Voilà, après à chaque fois cela dépend de ce que tu considères être ta donnée brute, mais voilà des exemples pour t'aider à comprendre…

par seïna » 06 août 2008, 23:49

Ah d'accord. En fait je n'avais, il est vrai, pas réfléchi aussi précisément. :oops: C'est par mimétisme que je faisais ça vu que j'apprends sur le tas. J'avais trouvé ça dans des scripts mais ce n'était pas des exemples par PDO, même si ça ne change rien. Donc je recopiais la manière de faire.
Donc c'est inversement, au moment de l'affichage que je vais traiter les infos de cette manière. En fait je faisais ça une fois au moment où les données entraient dans ma base mais je comprends maintenant ce que tu expliques sur l'intégrité des données.
Quand tu parles de traitement post formulaire c'est juste la vérification des champs en fait et voir si par exemple l'adresse mail ressemble bien à une adresse mail? Puis ça part tel quel dans ta base?
J'apprends, j'apprends un peu plus tous les jours.
:ordi:

par petitchevalroux » 06 août 2008, 23:48

Pour l'impact mémoire vrai je suis d'accord avec toi, mais bon je t'avouerai que je suis pas a 1ko prés sur la génération d'une page, aprés pour le htmlentities compilé dans php je te dirai que preg_match et str_replace le sont aussi et pourtant j'ai deja optmisé des scripts en virant quelques appels à ces fonctions.

Pour le cas de htmlentities je ne connais pas son temps d'éxécution mais je pars du principe qu'il ne sert à rien de faire 1 millions de fois une opération alors qu'on peut la faire une fois pour toute (une page est servie beaucoup plus souvent que modifié), et je suis pret à payer le prix de la non intégrité des données, surtout que les exports de base j'en fait pas des masses.

Aprés c'est une question de choix, j'ai fait le mien, tu as le tien et je le respecte.

par Sékiltoyai » 06 août 2008, 18:57

Peut être pour le faire une fois pour toute plutot que de le refaire à chaque affichage, vive les optims :D
L'intégrité des données est plus importante que la faible optimisation d'une telle opération. Et si on va par là, une entité html prend plus de place en mémoire que le caractère donc on perd de la performance. Enfin htmlentities est une fonction compilée dans le coeur de php, donc son temps d'exécution est négligeable sur l'échelle del'exécution du script…

par petitchevalroux » 06 août 2008, 18:43

Pour quelle raison obscure aurait-tu besoin que les entités HTML soient échappées lorsque tu les insères dans la base ?
Peut être pour le faire une fois pour toute plutot que de le refaire à chaque affichage, vive les optims :D

par Sékiltoyai » 06 août 2008, 16:47

Je vais répeter un principe de base qui est que l'on ne stocke pas les données formattées en base. Les bases de données sont faites pour stocker les données brutes. Pour quelle raison obscure aurait-tu besoin que les entités HTML soient échappées lorsque tu les insères dans la base ? Crois-tu que tu vas avoir une erreur sql parce que tu stockes <html> plutôt que >html< ?

Le formattage des données se fait à l'affichage, ton htmlentities n'a absolument rien à faire ici. Pour trim cela dépend à quoi il sert. Les données stockées en base doivent être les données réelles, c'est à dire après le traitement post-formulaire, et avant le traitement pré-affichage. Il faut donc que tu te demandes si la donnée réelle c'est ' machin machin ' ou 'machin machin', selon ton application, et donc si ton trim doit être un traitement sur la données entrantes ou les données sortantes.

par seïna » 06 août 2008, 16:04

Puisque je vois qu'il y a déjà une discussion ouverte sur une question que je me pose et qui est en relation avec celle ci, j'en profite.
Avis aux spécialistes de PDO :
Je sais que si j'utilise PDO avec des requêtes préparées je n'ai pas besoin d'utiliser la fonction quote pour les échappements.
Par contre je voudrais savoir si pour les variables à récupérer sur les zones texte de mes formulaires je dois quand même utiliser trim et ce qui s'en suit (voir ci-dessous) ou bien ce n'est plus nécessaire non plus.

Code : Tout sélectionner

$variable=trim(stripslashes(htmlentities($_POST["variable"])));
Merci de vos futures réponses…
:wink:

par cyruss » 13 juil. 2008, 11:17

Tu peux utiliser l'extension Filter de PHP par exemple.

++

par Sékiltoyai » 12 juil. 2008, 19:21

Euh, non je ne parle pas des magic quotes, sinon j'aurais dit magic quotes, pas requètes préparées :D
http://www.php.net/manual/fr/pdo.prepare.php

par nub » 12 juil. 2008, 13:50

merci beaucoup ça marche de nouveau !

Concernant les requêtes préparées, je ne sais pas trop ce que c'est ..
Si tu fait allusion au magic quotes, je tiens à m'en séparer car elles vont disparaitre avec php 6 !

[Note : ce message a été posté de manière anonyme avant d'être réattribué à son auteur]

par Sékiltoyai » 12 juil. 2008, 12:36

Sinon vu que tu utilises pdo, tu peux passer par les requêtes préparées…

par Ryle » 12 juil. 2008, 12:29

Oki, j'avais pas fait attention au fait que tu utilises PDO :)

En principe la méthode quote() devrait effectivement remplacer l'appel au real escape. Toutefois, cette méthode va en plus ajouter des apostrophes autour de la chaine retournée. Il ne faut donc pas que tu en rajoutes en plus dans la requête :
$pseudo = $dbh->quote($_POST['pseudo']); // variable a protéger  
$message = $dbh->quote($_POST['message']); // variable a protéger  
                     
$sql = "INSERT INTO minichat VALUES ('', ".$pseudo.", ".$message.", '".time()."')";