Comment une préparation évite-t-elle ou empêche-t-elle L'injection de SQL?

je sais que les traitements préparés évitent/empêchent L'Injection de SQL. Comment faut-il faire? Est-ce que la requête finale du formulaire qui est construite à L'aide de pré-compilations sera une chaîne ou autrement?

92
demandé sur Mark Rotteveel 2009-10-17 16:58:29

9 réponses

le problème avec L'injection SQL est qu'une entrée utilisateur est utilisée dans le cadre de la déclaration SQL. En utilisant des instructions préparées, vous pouvez forcer l'entrée de l'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 de l'utilisateur comme paramètre pour votre déclaration préparée mais que vous construisez votre commande SQL en joignant des chaînes, vous êtes encore vulnérable aux injections SQL même si en utilisant des déclarations préparées.

61
répondu tangens 2009-10-17 13:07:36

Envisager deux façons de faire la même chose:

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

ou

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

si "utilisateur" provient de l'entrée de l'utilisateur et l'entrée de l'utilisateur était

Robert'); DROP TABLE students; --

alors dans un premier temps, vous seriez drogué. Dans la seconde, tu serais en sécurité et le petit Bobby Tables serait inscrit à ton école.

156
répondu Paul Tomblin 2016-11-22 13:38:59

pour comprendre comment PreparedStatement empêche L'Injection SQL, nous devons comprendre les phases d'exécution de requête SQL.

1. Phase De Compilation. 2. Phase D'Exécution.

chaque fois que SQL server engine reçoit une requête, il doit passer par les phases ci-dessous,

Query Execution Phases

  1. l'Analyse et la Phase De Normalisation: Dans cette phase, la requête est vérifiée pour la syntaxe et la sémantique. Il vérifie si le tableau des références et les colonnes utilisées dans la requête existent ou non. Il a aussi beaucoup d'autres tâches à accomplir, mais n'entrons pas dans les détails.

  2. Phase De Compilation: Dans cette phase, les mots-clés utilisés dans la requête comme select, from, où etc sont convertis en format compréhensible par machine. C'est la phase où la requête est interprétée et les mesures correspondantes à prendre sont décidées. Il a aussi beaucoup d'autres tâches à accomplir, mais n'entrons pas dans les détails.

  3. Plan D'Optimisation De Requête: Dans cette phase, L'Arbre de décision est créé pour trouver les façons dont la requête peut être exécutée. Il découvre le nombre de façons dont requête peut être exécutée et les coûts associés à chaque voie de l'exécution de la Requête. Il choisit le meilleur plan pour exécuter une requête.

  4. Cache: Meilleur plan sélectionné dans le plan d'optimisation de requête est stocké dans la cache, de sorte que chaque fois que prochain la même requête arrive, elle n'a pas à passer par la Phase 1, la Phase 2 et la Phase 3 à nouveau. Lorsque la requête de la prochaine fois arrive, il sera vérifié directement dans le Cache et ramassé à partir de là exécuter.

  5. Phase D'Exécution: Dans cette phase, requête fournie obtient exécuté et les données sont retournées à l'utilisateur comme ResultSet objet.

le Comportement de PreparedStatement de l'API sur les étapes ci-dessus

  1. PreparedStatements ne sont pas complètes des requêtes SQL et contiennent de l'espace réservé(s), qui, au moment de l'exécution sont remplacés par les données fournies par l'utilisateur.

  2. chaque fois qu'un pré-enregistrement contenant des espaces réservés est passé dans SQL Server moteur, Il passe en dessous des phases

    1. Phase D'analyse et de normalisation
    2. Phase De Compilation
    3. Plan D'Optimisation Des Requêtes
    4. Cache (les requêtes compilées avec des espaces réservés sont stockées dans le Cache.)

UPDATE user set username=? et le mot de passe=? Où id=?

  1. la requête ci-dessus sera analysée, compilée avec des espaces réservés comme traitement spécial, optimisée et mise en Cache. La requête à ce stade est déjà compilée et convertie dans un format compréhensible par la machine. Donc nous pouvons dire que la requête stockée dans le cache est pré-compilée et seuls des espaces réservés doivent être remplacés avec des données fournies par l'utilisateur.

  2. maintenant au moment de l'exécution lorsque les données fournies par l'utilisateur entrent, requête pré-compilée est ramassé à partir de Cache et les espaces réservés sont remplacés avec des données fournies par l'utilisateur.

PrepareStatementWorking

(rappelez-vous, après que les titulaires de place sont remplacés par des données d'utilisateur, la requête finale n'est pas compilé / interprété à nouveau et SQL Server engine traite les données de l'utilisateur comme des données pures et non SQL qui a besoin d'être analysé ou compilé à nouveau; c'est la beauté de PreparedStatement.)

si la requête ne doit pas passer par la phase de compilation à nouveau, alors quelles que soient les données remplacées sur le placeholders sont traités comme des données pures et n'a pas de sens pour le moteur de Serveur SQL et il directement exécute la requête.

Note: c'est la phase de compilation après la phase d'analyse, qui comprend / interprète la requête structure et donne significative comportement. En cas de PreparedStatement, la requête est compilé une seule fois et la requête compilée en cache est ramassée tout le temps pour remplacer données utilisateur et exécuter.

en raison d'une fonction de compilation unique de PreparedStatement, il est libre D'Injection SQL attaque.

vous pouvez obtenir une explication détaillée avec l'exemple ici: http://javabypatel.blogspot.in/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html

64
répondu Jayesh 2017-10-26 06:39:06

le SQL utilisé dans une déclaration préparée est précompilé sur le conducteur. À partir de ce moment, les paramètres sont envoyés au pilote sous forme de valeurs littérales et non exécutables de portions de SQL; ainsi, aucun SQL ne peut être injecté à l'aide d'un paramètre. Un autre effet secondaire bénéfique des paramètres pré-compilés (précompilation + envoi de paramètres uniquement) est l'amélioration des performances lors de l'exécution de la déclaration plusieurs fois, même avec des valeurs différentes pour les paramètres (en supposant que le pilote supporte PreparedStatements) car le pilote n'a pas à effectuer D'analyse et de compilation SQL chaque fois que les paramètres changent.

25
répondu Travis Heseman 2009-10-17 13:38:30

je deviner ce sera une chaîne de caractères. Mais les paramètres d'entrée seront envoyés à la base de données et les casts/conversions appropriées seront appliquées avant de créer une déclaration SQL réelle.

pour vous donner un exemple, il pourrait essayer de voir si la distribution/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))

essayer un exemple avec une déclaration SQL acceptant un numérique paramètre.

Maintenant, essayez de passer une variable de chaîne (avec un contenu numérique qui est acceptable comme paramètre numérique). Ne faire aucune erreur?

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

3
répondu shahkalpesh 2009-10-17 13:33:12

la déclaration préparée est plus sûre. Il convertira un paramètre au type spécifié.

par exemple stmt.setString(1, user); convertira le paramètre user en chaîne de caractères.

supposons que le paramètre contient une chaîne SQL contenant une commande exécutable : utiliser une instruction préparée ne permettra pas cela.

il ajoute metacharacter (A. K. A. auto conversion).

cela le rend plus sûr.

3
répondu Guru R Handa 2013-05-15 16:05:54

comme expliqué dans ce post , le PreparedStatement seul ne vous aide pas si vous êtes encore chaînes de concaténation.

par exemple, un attaquant rebelle peut encore faire ce qui suit:

non seulement SQL, mais même JPQL ou HQL peuvent être compromis si vous n'utilisez pas les paramètres de bind.

en bref, vous ne devriez jamais utiliser la concaténation de chaîne lors de la construction D'énoncés SQL. Utilisez une API dédiée à cet effet:

1
répondu Vlad Mihalcea 2018-01-05 19:31:16

injection SQL: quand l'Utilisateur a la chance d'entrer quelque chose qui pourrait faire partie de la déclaration sql

par exemple:

String query = " INSERT INTO students VALUES (‘"+user + "‘)"

quand l'utilisateur entre "Robert’); les étudiants de DROP TABLE; -" comme l'entrée, il provoque L'injection SQL

Comment instruction préparée empêche cela?

String query = " INSERT INTO students VALUES (‘" + ":nom de" + "‘)"

paramètres.addValue("nom", utilisateur);

= > quand l'utilisateur entre à nouveau "Robert’); les étudiants de DROP TABLE; -", la chaîne d'entrée est précompilée sur le pilote comme valeurs littérales et je suppose qu'il peut être moulé comme:

CAST ('Robert’); DROP TABLE students; -' AS varchar (30))

Ainsi, à la fin, la chaîne sera littéralement inséré comme le nom de la table.

http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection /

1
répondu jack 2018-01-10 14:05:55

déclaration préparée:

1) la précompilation et la mise en cache côté DB de L'instruction SQL permettent une exécution globalement plus rapide et la possibilité de réutiliser la même instruction SQL dans les lots.

2) prévention automatique des attaques par injection SQL grâce à la possibilité d'échapper aux guillemets et autres caractères spéciaux. Notez que cela nécessite que vous utilisiez n'importe laquelle des méthodes de PreparedStatement setXxx() pour définir la valeur.

0
répondu Mukesh Kumar 2015-11-18 11:29:18