Je comprends que vous ne devriez JAMAIS faire confiance aux entrées utilisateur d'un formulaire, principalement en raison du risque d'injection SQL.
Cependant, cela s'applique-t-il également à un formulaire où la seule entrée provient d'une ou plusieurs listes déroulantes (voir ci-dessous)?
J'enregistre le $_POST['size']
dans une session qui est ensuite utilisée dans tout le site pour interroger les différentes bases de données (avec une mysqli
requête Select) et toute injection SQL les endommagerait certainement (éventuellement les supprimerait).
Il n'y a pas de zone pour l'entrée utilisateur tapée pour interroger les bases de données, uniquement des listes déroulantes.
<form action="welcome.php" method="post">
<select name="size">
<option value="All">Select Size</option>
<option value="Large">Large</option>
<option value="Medium">Medium</option>
<option value="Small">Small</option>
</select>
<input type="submit">
</form>
php
mysql
mysqli
sql-injection
Lambeaux
la source
la source
<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)Réponses:
Vous pouvez faire quelque chose d'aussi simple que l'exemple suivant pour vous assurer que la taille publiée correspond à ce que vous attendez.
Ensuite, utilisez mysqli_ * si vous utilisez une version de php> = 5.3.0 que vous devriez être, pour enregistrer votre résultat. S'il est utilisé correctement, cela aidera à l'injection SQL.
la source
mysqli_real_escape_string
. Échappez également correctement les valeurs lors de leur sortie (par exemple, utilisez htmlspecialchars () dans un document HTML).in_array
àtrue
pour une comparaison stricte. Je ne suis pas sûr de ce qui pourrait mal tourner, mais une comparaison lâche est assez bizarre.Oui, vous devez vous protéger contre cela.
Laissez-moi vous montrer pourquoi, en utilisant la console développeur de Firefox:
Si vous ne nettoyez pas ces données, votre base de données sera détruite. (Ce n'est peut-être pas une instruction SQL totalement valide, mais j'espère avoir compris mon point de vue.)
Ce n'est pas parce que vous avez limité les options disponibles dans votre liste déroulante que vous avez limité les données que je peux envoyer à votre serveur.
Si vous avez essayé de restreindre davantage ce comportement en utilisant sur votre page, mes options incluent la désactivation de ce comportement ou simplement l'écriture d'une requête HTTP personnalisée sur votre serveur qui imite de toute façon cette soumission de formulaire. Il y a un outil appelé curl utilisé pour exactement cela, et je pense que la commande pour soumettre cette injection SQL ressemblerait de toute façon à ceci:
(Ce n'est peut-être pas une commande curl totalement valide, mais encore une fois, j'espère avoir compris mon point de vue.)
Alors, je répète:
Ne faites JAMAIS confiance à l'entrée de l'utilisateur. Protégez-vous TOUJOURS.
Ne présumez pas qu'aucune entrée utilisateur n'est jamais sûre. Il est potentiellement dangereux même s'il arrive par un autre moyen qu'un formulaire. Rien de tout cela n'est assez fiable pour renoncer à vous protéger de l'injection SQL.
la source
curl
. Nettoyez TOUJOURS les entrées côté serveur !curl
. Les gens ne comprennent pas que vous pouvez envoyer une requête HTTP de n'importe où à n'importe où en utilisant n'importe quel format et en passant des valeurs, il appartient au serveur de s'assurer que la requête est valide avant de la traiter.Comme cette question a été identifiée avec injection SQL, voici une réponse concernant ce type particulier d'attaque:
Comme vous l'avez dit dans les commentaires, vous devez utiliser des instructions préparées pour chaque requête impliquant des données variables, sans exception .
Indépendamment de tout truc HTML!
Il est essentiel de comprendre que les requêtes SQL doivent être correctement formatées quels que soient les facteurs externes, que ce soit une entrée HTML ou autre.
Bien que vous puissiez utiliser la liste blanche suggérée dans d'autres réponses à des fins de validation d'entrée, cela ne devrait affecter aucune action liée à SQL - elles doivent rester les mêmes, peu importe si vous avez validé l'entrée HTML ou non. Cela signifie que vous devez toujours utiliser des instructions préparées lors de l'ajout de variables dans la requête.
Vous trouverez ici une explication détaillée, pourquoi les instructions préparées sont indispensables et comment les utiliser correctement et où elles ne sont pas applicables et que faire dans ce cas: Le guide de l'auto-stoppeur sur la protection contre les injections SQL
De plus, cette question a été identifiée avec mysqli. Surtout par accident, je présume, mais de toute façon, je dois vous avertir que le mysqli brut n'est pas une substitution adéquate aux anciennes fonctions mysq_ * . Tout simplement parce que s'il est utilisé dans l'ancien style, il n'ajoutera aucune sécurité. Bien que la prise en charge des instructions préparées soit pénible et gênante, au point que l'utilisateur PHP moyen est tout simplement incapable de les essayer. Ainsi, si aucun ORM ou une sorte de bibliothèque d'abstraction n'est option, alors PDO est votre seul choix.
la source
random
?Oui.
N'importe qui peut usurper n'importe quoi pour les valeurs qui sont réellement envoyées -
Donc, pour valider les menus déroulants, vous pouvez simplement vérifier que la valeur avec laquelle vous travaillez était dans la liste déroulante - quelque chose comme celui-ci serait la meilleure façon (la plus paranoïaque):
la source
Une façon de se protéger contre les utilisateurs qui modifient vos listes déroulantes à l'aide de la console consiste à n'utiliser que des valeurs entières. Ensuite, vous pouvez valider que la valeur POST contient un entier et utiliser un tableau pour le convertir en texte si nécessaire. Par exemple:
Ensuite, vous pouvez utiliser
$size
dans votre requête en sachant qu'il ne contiendra jamaisFALSE
qu'un entier.la source
filter_input
sinon un chèque côté serveur? Personne ne peut publier autre chose qu'un entier.filter_input
pièce pour la validation, sinon c'est aussi utile qu'une théière en chocolat pour la sécurité.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.
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.
la source
Votre navigateur Web ne "sait" pas qu'il reçoit une page de php, il ne voit que du HTML. Et la couche http en sait encore moins que cela. Vous devez être capable de gérer presque tous les types d'entrées qui peuvent traverser la couche http (heureusement pour la plupart des entrées, php donnera déjà une erreur). Si vous essayez d'empêcher les requêtes malveillantes de gâcher votre base de données, vous devez supposer que le gars à l'autre bout du fil sait ce qu'il fait et qu'il n'est pas limité à ce que vous pouvez voir dans votre navigateur dans des circonstances normales ( sans parler de ce que vous pouvez manipuler avec les outils de développement d'un navigateur). Alors oui, vous devez prendre en compte toutes les entrées de votre liste déroulante, mais pour la plupart des entrées, vous pouvez donner une erreur.
la source
Le fait que vous ayez limité l'utilisateur à n'utiliser que les valeurs d'une certaine liste déroulante n'est pas pertinent. Un utilisateur technique peut capturer la requête http envoyée à votre serveur avant qu'elle ne quitte son réseau, la modifier à l'aide d'un outil tel qu'un serveur proxy local, puis la poursuivre. À l'aide de la demande modifiée, ils peuvent envoyer des valeurs de paramètres qui ne sont pas celles que vous avez spécifiées dans la liste déroulante. Les développeurs doivent avoir la mentalité que les restrictions des clients n'ont souvent aucun sens, car tout ce qui touche un client peut être modifié. La validation du serveur est requise à chaque point d'entrée des données client. Les attaquants comptent sur la naïveté des développeurs dans ce seul aspect.
la source
Il est préférable d'utiliser une requête paramétrée afin de garantir contre l'injection SQL. Dans ce cas, l'apparence de la requête serait la suivante:
Lorsque vous fournissez une requête comme celle-ci avec du texte dont l'intégrité n'est pas vérifiée (l'entrée n'est pas validée sur le serveur) et qu'elle contient du code d'injection SQL, elle sera gérée correctement. En d'autres termes, la requête entraînera quelque chose comme ceci dans la couche de base de données:
Cela sélectionnera simplement 0 résultats lors de son retour, ce qui rendra la requête inefficace en causant réellement des dommages à la base de données sans avoir besoin d'une liste blanche, d'une vérification de vérification ou d'autres techniques. Veuillez noter qu'un programmeur responsable fera la sécurité dans les couches, et validera souvent en plus du paramétrage des requêtes. Cependant, il y a très peu de raisons de ne pas paramétrer vos requêtes du point de vue des performances et la sécurité ajoutée par cette pratique est une bonne raison pour vous familiariser avec les requêtes paramétrées.
la source
Tout ce qui est soumis à partir de votre formulaire arrive sur votre serveur sous forme de texte à travers les fils. Rien n'empêche quiconque de créer un bot pour imiter le client ou le saisir à partir d'un terminal s'il le souhaite. Ne supposez jamais que parce que vous avez programmé le client, il agira comme vous le pensez. C'est vraiment facile à usurper.
Exemple de ce qui peut et se produira lorsque vous faites confiance au client.
la source
Un pirate informatique peut contourner complètement le navigateur, y compris la vérification du formulaire Javascript, en envoyant une requête via Telnet. Bien sûr, il regardera le code de votre page html pour obtenir les noms de champs qu'il doit utiliser, mais à partir de là, c'est «tout va» pour lui. Vous devez donc vérifier toutes les valeurs soumises sur le serveur comme si elles ne provenaient pas de votre page html.
la source