Les autres réponses couvrent déjà ce que vous devez savoir. Mais peut-être que cela aide à clarifier un peu plus:
Il y a DEUX CHOSES que vous devez faire:
1. Validez les données du formulaire.
Comme le montre très clairement la réponse de Jonathan Hobbs , le choix de l'élément html pour la saisie du formulaire ne fait aucun filtrage fiable pour vous.
La validation est généralement effectuée d'une manière qui ne modifie pas les données, mais qui montre à nouveau le formulaire, avec les champs marqués comme "Veuillez corriger cela".
La plupart des frameworks et CMS ont des générateurs de formulaires qui vous aident dans cette tâche. Et pas seulement cela, ils aident également contre CSRF (ou "XSRF"), qui est une autre forme d'attaque.
2. Variables de nettoyage / d'échappement dans les instructions SQL.
.. ou laissez les déclarations préparées faire le travail à votre place.
Si vous créez une instruction SQL (My) avec des variables, fournies par l'utilisateur ou non, vous devez échapper et citer ces variables.
En général, une telle variable que vous insérez dans une instruction MySQL doit être soit une chaîne, soit quelque chose que PHP peut transformer de manière fiable en une chaîne que MySQL peut digérer. Tels que les nombres.
Pour les chaînes, vous devez ensuite choisir l'une des nombreuses méthodes pour échapper à la chaîne, c'est-à-dire remplacer tous les caractères qui auraient des effets secondaires dans MySQL.
- Dans MySQL + PHP à l'ancienne, mysql_real_escape_string () fait le travail. Le problème est qu'il est beaucoup trop facile à oublier, vous devez donc absolument utiliser des instructions préparées ou des générateurs de requêtes.
- Dans MySQLi, vous pouvez utiliser des instructions préparées.
- La plupart des frameworks et CMS fournissent des générateurs de requêtes qui vous aident dans cette tâche.
Si vous avez affaire à un nombre, vous pouvez omettre les échappements et les guillemets (c'est pourquoi les instructions préparées permettent de spécifier un type).
Il est important de souligner que vous échappez aux variables pour l'instruction SQL, et PAS pour la base de données elle-même . La base de données stockera la chaîne d'origine, mais l'instruction a besoin d'une version échappée.
Que se passe-t-il si vous en omettez un?
Si vous n'utilisez pas la validation de formulaire , mais que vous nettoyez votre entrée SQL, vous pourriez voir toutes sortes de mauvaises choses se produire, mais vous ne verrez pas d'injection SQL! (*)
Tout d'abord, cela peut amener votre application dans un état que vous n'aviez pas prévu. Par exemple, si vous souhaitez calculer l'âge moyen de tous les utilisateurs, mais qu'un utilisateur a donné "aljkdfaqer" pour l'âge, votre calcul échouera.
Deuxièmement, il peut y avoir toutes sortes d'autres attaques par injection que vous devez prendre en compte: par exemple, l'entrée utilisateur peut contenir du javascript ou d'autres éléments.
Il peut encore y avoir des problèmes avec la base de données: par exemple, si un champ (colonne de table de base de données) est limité à 255 caractères et que la chaîne est plus longue que cela. Ou si le champ n'accepte que des nombres et que vous essayez d'enregistrer une chaîne non numérique à la place. Mais ce n'est pas une "injection", il s'agit simplement de "planter l'application".
Mais, même si vous avez un champ de texte libre dans lequel vous autorisez toute entrée sans aucune validation, vous pouvez toujours l'enregistrer dans la base de données comme ça, si vous l'échappez correctement quand il va à une instruction de base de données. Le problème survient lorsque vous souhaitez utiliser cette chaîne quelque part.
(*) ou ce serait quelque chose de vraiment exotique.
Si vous n'échappez pas aux variables pour les instructions SQL , mais que vous avez validé l'entrée du formulaire, vous pouvez toujours voir de mauvaises choses se produire.
Tout d'abord, vous risquez que lorsque vous enregistrez des données dans la base de données et que vous la chargez à nouveau, ce ne sera plus les mêmes données, "perdues lors de la traduction".
Deuxièmement, cela peut entraîner des instructions SQL non valides et ainsi planter votre application. Par exemple, si une variable contient un guillemet ou un guillemet double, selon le type de guillemet que vous utilisez, vous obtiendrez une déclaration MySQL invalide.
Troisièmement, cela peut toujours provoquer une injection SQL.
Si votre entrée utilisateur à partir de formulaires est déjà filtrée / validée, l' injection intentionnelle de SQl peut devenir moins probable, SI votre entrée est réduite à une liste d'options codée en dur, ou si elle est limitée aux nombres. Mais toute entrée de texte libre peut être utilisée pour l'injection SQL, si vous n'échappez pas correctement les variables dans les instructions SQL.
Et même si vous n'avez aucune entrée de formulaire, vous pouvez toujours avoir des chaînes de toutes sortes de sources: lues à partir du système de fichiers, extraites d'Internet, etc. Personne ne peut garantir que ces chaînes sont sûres.
<select>
entrée. En effet, même un utilisateur légèrement technique pourrait ajouter des options supplémentaires en utilisant la console du navigateur. si vous conservez une liste blanche de tableau des valeurs disponibles et comparez l'entrée avec celle-ci, vous pouvez atténuer cela (et vous devriez car cela empêche les valeurs indésirables)