Comment un PreparedStatement évite-t-il ou empêche-t-il l'injection SQL?


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

Author: Mark Rotteveel, 2009-10-17

9 answers

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 comme paramètre pour votre instruction préparée mais que vous construisez plutôt votre commande SQL en joignant des chaînes ensemble, vous êtes toujours vulnérable aux injections SQL même lorsque vous utilisez des instructions préparées.

 61
Author: tangens, 2009-10-17 13:07:36

Considérons 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 "user" venait de l'entrée utilisateur et que l'entrée utilisateur était

Robert'); DROP TABLE students; --

Alors en premier lieu, vous seriez arrosé. Dans la seconde, vous seriez en sécurité et les petites tables Bobby seraient enregistrées pour votre école.

 156
Author: 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 des requêtes SQL.

1. Phase de Compilation. 2. Phase d'exécution.

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

Phases D'Exécution Des Requêtes

  1. Phase d'analyse et de normalisation: Dans cette phase, la syntaxe et la sémantique de la requête sont vérifiées. Il vérifie si les références table et colonnes utilisées dans la requête existent ou non. Il a aussi beaucoup d'autres tâches à faire, mais n'allons pas dans les détails.

  2. Phase de compilation: Dans cette phase, les mots clés utilisés dans la requête select, from, où etc sont convertis en format compréhensible par la machine. C'est la phase où la requête est interprétée et l'action correspondante à prendre est décidée. Il a aussi beaucoup d'autres tâches à faire, mais n'allons pas dans les détails.

  3. Plan d'optimisation des requêtes: 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 la requête peut être exécutée et le coût associé à chaque façon de l'exécution de la Requête. Il choisit le meilleur plan pour exécuter une requête.

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

  5. Phase D'Exécution: Dans cette phase, la requête fournie est exécutée et les données sont renvoyées à l'utilisateur en tant qu'objet ResultSet.

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

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

  2. Chaque fois que tout PreparedStatment contenant des espaces réservés est transmis au moteur SQL Server, Il passe par les phases ci-dessous

    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.)

METTRE à JOUR le nom d'utilisateur du jeu d'utilisateurs=? 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 au format compréhensible par la machine. Nous pouvons donc dire que la requête stockée dans le cache est Pré-compilée et seuls les espaces réservés doivent être remplacés par des données fournies par l'utilisateur.

  2. Maintenant, au moment de l'exécution lorsque les données fournies par l'utilisateur arrivent, la requête pré-compilée est extraite du cache et les espaces réservés sont remplacés par des données fournies par l'utilisateur.

Preparedstatementworking

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

Si la requête n'a pas à passer à nouveau par la phase de compilation, alors quelles que soient les données remplacées sur le les espaces réservés sont traités comme des données pures et n'ont aucune signification pour SQL Server Engine et directement exécute la requête.

Remarque: Il est la compilation phase après la phase d'analyse, qui comprend / interprète la requête structure et lui donne un comportement significatif. En cas de PreparedStatement, la requête est compilé une seule fois et mis en cache la requête compilée est récupérée tout le temps pour remplacer données utilisateur et exécuter.

En raison de la fonctionnalité de compilation unique de PreparedStatement, il est exempt d'injection SQL attaque.

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

 64
Author: Jayesh, 2017-10-26 06:39:06

Le SQL utilisé dans un PreparedStatement est précompilé sur le pilote. À partir de ce moment, les paramètres sont envoyés au pilote sous forme de valeurs littérales et non de parties exécutables de SQL; ainsi, aucun SQL ne peut être injecté à l'aide d'un paramètre. Un autre effet secondaire bénéfique de PreparedStatements ( précompilation + envoi uniquement de paramètres) est l'amélioration des performances 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) comme le pilote n'a pas à effectuer d'analyse et de compilation SQL chaque fois que les paramètres changent.

 25
Author: Travis Heseman, 2009-10-17 13:38:30

I devinez ce sera une chaîne. Mais les paramètres d'entrée seront envoyés à la base de données et la conversion/conversion appropriée sera appliquée avant de créer une instruction SQL réelle.

Pour vous donner un exemple, il pourrait essayer de voir si la DISTRIBUTION/conversion fonctionne.
Si cela fonctionne, il pourrait en 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 acceptant un paramètre numérique.
Maintenant, essayez de passer une variable 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 string (avec un contenu qui n'est pas acceptable en tant que paramètre numérique). Voir ce qui se passe?

 3
Author: shahkalpesh, 2009-10-17 13:33:12

L'instruction 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.

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

Il ajoute un métacaractère (alias conversion automatique) à cela.

Cela le rend plus sûr.

 3
Author: Guru R Handa, 2013-05-15 16:05:54

Comme expliqué dans cet article, le PreparedStatement seul ne vous aide pas si vous concaténez toujours des chaînes.

Par exemple, un attaquant malveillant peut toujours effectuer les opérations suivantes:

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

En fin de compte, vous ne devez jamais utiliser la concaténation de chaînes lors de la construction d'instructions SQL. Utilisez une API dédiée à cet effet:

 1
Author: Vlad Mihalcea, 2018-01-05 19:31:16

Injection SQL: lorsque l'utilisateur a la possibilité d'entrer quelque chose qui pourrait faire partie de l'instruction sql

Par exemple:

String query = " INSÉRER DANS LES VALEURS DES étudiants ('"+user+"‘) "

Lorsque l'utilisateur entre "Robert'); DROP TABLE students; – " comme entrée, il provoque une injection SQL

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

String query = " INSÉRER DANS LES VALEURS DES étudiants(‘" + ":nom" + " '‘ "

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

=> lorsque l'utilisateur input again "Robert'); DROP TABLE students;–", la chaîne d'entrée est précompilée sur le pilote en tant que valeurs littérales et je suppose qu'elle peut être castée comme:

CAST(‘Robert’); DROP TABLE élèves; –‘ varchar(30))

Donc à la fin, la chaîne sera littéralement insérée comme nom dans la table.

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

 1
Author: jack, 2018-01-10 14:05:55

PreparedStatement:

1) La précompilation et la mise en cache côté base de données de l'instruction SQL conduisent à une exécution globale plus rapide et à la possibilité de réutiliser la même instruction SQL par lots.

2) Prévention automatique des attaques par injection SQL par échappement intégré des guillemets et autres caractères spéciaux. Notez que cela nécessite que vous utilisiez l'une des méthodes PreparedStatement setXxx () pour définir la valeur.

 0
Author: Mukesh Kumar, 2015-11-18 11:29:18