Question

Dans les deux requêtes 1 et 2, le texte de la zone de texte est inséré dans la base de données. Quelle est la signification de la requête paramétrée ici?

  1. Qui passe txtTagNumber comme paramètre de requête

    SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
    cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
    cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
    
  2. Conversion txtTagNumber à un entier avant de construire la requête

    int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
    INSERT into Cars values(tagnumber.Text); /* then is it the same? */
    

En outre, ici, j'utiliserais une validation d'expression régulière pour arrêter l'insertion de caractères illégaux.

Était-ce utile?

La solution

Les requêtes paramétrées font une bonne substitution des arguments avant d'exécuter la requête SQL. Il supprime complètement la possibilité d'une entrée "sale" modifiant la signification de votre requête. Autrement dit, si l'entrée contient SQL, elle ne peut pas faire partie de ce qui est exécuté car le SQL n'est jamais injecté dans l'instruction résultante.

Autres conseils

L'injection SQL se produit lorsqu'un paramètre possible a SQL à l'intérieur et que les chaînes ne sont pas gérées comme elle devrait l'être

par exemple:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + condition+''";

et la condition est une chaîne provenant de l'utilisateur dans la demande. Si la condition est malveillante, dites par exemple:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + "a' ;drop table  mytable where '1=1"+"'";

Vous pourriez finir par exécuter des scripts malveillants.

Mais en utilisant les paramètres, l'entrée sera nettoyée de tous les caractères qui pourraient échapper aux caractères de chaîne ...

Vous pouvez être assuré, peu importe ce qui intervient ne pourra pas exécuter des scripts Inject.

en utilisant l'objet de commande avec des paramètres que le SQL réellement exécuté ressemblerait à ceci

select * from mytable where rowname = 'a'';drop table mytable where 1=1'''

Dans Essense, il cherchera une ligne avec Rowname = A '; Table Drop Table Mytable où 1 = 1' et ne pas exécuter le script restant

Imaginez une requête SQL dynamique

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
Pass=' + password

donc une simple injection SQL serait juste de mettre le nom d'utilisateur ' OR 1=1-- Cela ferait efficacement la requête SQL:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
+ password

Cela dit Sélectionner tous les clients où leur nom d'utilisateur est vide ('') ou 1 = 1, qui est un booléen, équivalant à vrai. Ensuite, il utilise - pour commenter le reste de la requête. Donc, cela imprimera tout le tableau client ou fera ce que vous voulez, si vous vous connectez, il se connectera avec les privilèges du premier utilisateur, qui peuvent souvent être l'administrateur.

Maintenant, les requêtes paramétrées le font différemment, avec du code comme:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'

paramètres.add ("utilisateur", nom d'utilisateur) Paramètres.add ("pass", mot de passe)

où le nom d'utilisateur et le mot de passe sont des variables pointant vers le nom d'utilisateur et le mot de passe entrés associés

Maintenant, à ce stade, vous pensez peut-être que cela ne change rien du tout. Vous pouvez sûrement encore mettre dans le champ d'utilisateur quelque chose comme personne ou 1 = 1 '-, faisant efficacement la requête:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
Pass=?'

Et cela semblerait être un argument valable. Mais vous auriez tort.

La façon dont les requêtes paramétrées fonctionnent, est que la SQLQuery est envoyée sous forme de requête, et la base de données sait exactement ce que cette requête fera, et ce n'est qu'alors qu'il insère le nom d'utilisateur et les mots de passe simplement sous forme de valeurs. Cela signifie qu'ils ne peuvent pas affecter la requête, car la base de données sait déjà ce que fera la requête. Donc, dans ce cas, il chercherait un nom d'utilisateur de "Nobody OR 1=1'--" et un mot de passe vide, qui devrait être faux.

Pris à partir de

Les requêtes paramétrées gèrent tout - pourquoi aller aux ennuis?

Avec des requêtes paramétrées, en plus de l'injection générale, vous obtenez tous les types de données manipulés, les nombres (int et float), les chaînes (avec des citations intégrées), les dates et les heures (aucun problème de formatage ou problèmes de localisation lorsque .tostring () n'est pas appelé avec la culture invariante et votre client se déplace vers une machine avec et format de date inattendu).

Les requêtes paramétrées permettent au client de passer les données à fortement former le texte de la requête. Où le plus libre du texte, vous effectuez une validation + s'échapper. Bien sûr, le paramétrage n'aide pas contre d'autres types d'injection, mais comme le paramètre est passé séparément, ils ne sont pas utilisés comme requête de texte d'exécution.

Une bonne analogie serait le bit d'exécution "récent" utilisé avec la plupart du processeur moderne et du système d'exploitation pour protéger du débordement de tampon. Il permet toujours le débordement du tampon mais empêche l'exécution des données injectées.

Il est tout à fait compréhensible pourquoi on le ressentirait.

sqlQuery = "select * from users where username='+username+';"

contre

sqlQuery = "select * from users where username=@username;"

Les deux requêtes ci-dessus semblent faire la même chose, mais elles ne le font pas.

Le premier utilise les entrées pour une requête, la seconde décide de la requête mais remplace uniquement les entrées telles qu'elles sont lors de l'exécution de la requête.

Pour être plus clair, les valeurs des paramètres se trouvent dans la pile où la mémoire des variables est stockée et est utilisée pour la recherche en cas de besoin.

Donc, si nous devions donner ' OR '1'='1 Comme l'entrée dans le nom d'utilisateur, le premier dynamiquement Construisez une nouvelle requête ou des requêtes dans le cadre de la chaîne de requête SQL sqlQuery qui est ensuite exécuté.

Tandis que sur la même entrée, ce dernier chercherait ' OR '1'=' dans le username champ du users table avec le statiquement Requête spécifiée dans la chaîne de requête sqlQuery

Juste pour le consolider, c'est ainsi que vous utilisez des paramètres pour faire une requête:

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";

command.Parameters.Add(parameter);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top