151 votes

Comment un état préparé évite-t-il ou empêche-t-il une injection SQL?

Je sais que PreparedStatements évite / empêche l'injection SQL. Comment ça fait ça? La requête de formulaire finale construite à l'aide de PreparedStatements sera-t-elle une chaîne ou autrement?

225voto

Paul Tomblin Points 83687

Considérons deux manières de faire la même chose:

 Statement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();
 

Ou

 Statement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
 

Si "utilisateur" provient d'une entrée utilisateur et que cette entrée est

 Robert'); DROP TABLE students; --
 

Ensuite, dans un premier temps, vous seriez arrosé. Dans le second cas, vous seriez en sécurité et Little Bobby Tables serait inscrit à votre école.

87voto

tangens Points 17733

Le problème avec l'injection SQL est qu'une entrée utilisateur est utilisée dans le cadre de l'instruction SQL. En utilisant des instructions préparées, vous pouvez forcer l'entrée utilisateur à être traitée comme le contenu d'un paramètre (et non comme une partie de la commande SQL).

Mais si vous n'utilisez pas l'entrée utilisateur en tant que paramètre pour votre instruction préparée, mais construisez plutôt votre commande SQL en joignant des chaînes, vous restez vulnérable aux injections SQL, même lorsque vous utilisez des instructions préparées.

28voto

Travis Heseman Points 4646

Le SQL utilisé dans un PreparedStatement est précompilé sur le conducteur. À partir de ce moment, les paramètres sont envoyés au conducteur comme des valeurs littérales et non exécutable portions de SQL; donc pas de SQL peut être injecté à l'aide d'un paramètre. D'un autre côté bénéfique effet de PreparedStatements (précompilation + envoi de paramètres) est l'amélioration de la performance lors de l'exécution de l'instruction plusieurs fois, même avec des valeurs différentes pour les paramètres (en supposant que le pilote prend en charge PreparedStatements) que le conducteur n'a pas à effectuer de SQL analyse et la compilation à chaque fois que le changement des paramètres.

4voto

shahkalpesh Points 21553

Je suppose que ce sera une chaîne de caractères. Mais les paramètres d'entrée vous sera envoyé à la base de données et un cast/conversions sera appliqué avant la création d'une véritable instruction SQL.

Pour vous donner un exemple, il pourrait essayer et de voir si le CAST/la Conversion fonctionne.
Si cela fonctionne, cela peut créer une déclaration finale.

   SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))

Essayez un exemple avec une instruction SQL d'accepter un paramètre numérique.
Maintenant, essayez de passer une variable chaîne (avec un contenu numérique qui est acceptable en tant que paramètre numérique). Ne faire aucune erreur?

Maintenant, essayez de passer une variable chaîne (avec un contenu qui n'est pas acceptable en tant que paramètre numérique). Voir ce qui se passe?

3voto

Guru R Handa Points 67

La déclaration préparée est plus sécurisée. Cela convertira un paramètre dans le type spécifié.

Par exemple, stmt.setString(1, user); convertira le paramètre user en chaîne.

Supposons que le paramètre contienne une chaîne SQL contenant une commande exécutable : l'utilisation d'une instruction préparée ne le permettra pas.

Il ajoute le métacaractère (aka conversion automatique) à cela.

Cela le rend plus sûr.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X