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?
Réponses
Trop de publicités?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.
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.
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.
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?
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.