2011-07-11 5 views
1

J'ai construit un système prototype avec quelques requêtes de base de données. Comme c'était juste un prototype et que j'étais très nouveau dans les bases de données, j'ai juste utilisé une chaîne directe. Ceci est la chaîne je et il fonctionne très bien:VB.NET - Problèmes avec les requêtes paramétrées

command = New OleDbCommand("SELECT * FROM " + prefix + "CanonicForms WHERE Type=1 AND Canonic_Form='" + item + "'", dictionary_connection) 

Maintenant, en le mettant dans un système réel, je voulais utiliser la méthode paramétré plus sûre, donc après quelques googler je suis venu avec ceci:

command = New OleDbCommand("SELECT * FROM @prefix WHERE Type=1 AND [email protected]", dictionary_connection) 
command.Parameters.AddWithValue("@prefix", prefix + "CanonicForms") 
command.Parameters.AddWithValue("@form", item) 

Mais tout ce que j'obtiens est une erreur pour une clause de requête incomplète. Qu'ai-je fait différemment entre les deux?

Répondre

3

Le nom de votre table ne peut pas être un paramètre. Vous devrez peut-être faire une forme de concaténation. Ce n'est pas vraiment un paramètre dans le sens formel du mot.

+0

Vraiment? Si vous avez un nom de table qui dépend d'une sorte d'entrée, cela ne vous ouvre-t-il pas autant les problèmes d'injection que de ne pas utiliser un paramètre? Si j'utilise simplement la concaténation pour la table, je veux dire – cost

+0

Je dirais que cela pourrait vous ouvrir. Vous pourriez vouloir "assainir" le nom de la table - je pense que c'est quelque chose qui est assez commun. Personne n'aime concaténer une déclaration SQL, mais il y a des moments où vous n'avez pas vraiment le choix. –

+1

@cost: l'injection SQL est le résultat de la concaténation d'une entrée UNVERIFIED/aseptisée. Si vous vérifiez l'entrée, vous n'êtes pas ouvert à l'injection SQL. Dans ce cas, la méthode préférée pour vérifier l'entrée consisterait à mapper ce que l'utilisateur entre dans un nom de table connu (sans utiliser directement l'entrée des utilisateurs). Si cela n'est pas possible, vérifiez d'abord que le nom de la table existe avant de concaténer il (c'est-à-dire utiliser une requête paramétrée contre information_schema.tables). Donc, oui, il est ouvert à l'injection, mais il ne doit pas être * vulnérable * à l'injection. – jmoreno

1

Comme les états ek_ny, votre nom de table ne peut pas être un paramètre.

Si vous êtes vraiment paranoïaque à propos de l'injection, vérifiez le nom de la table transmise par rapport à une liste blanche de valeurs autorisées avant de créer la chaîne SQL.

1

@cost, je suis d'accord que ce serait bien, mais ce n'est tout simplement pas une fonctionnalité qui existe. En général, il est supposé que vos clauses WHERE constituent la partie dynamique de la requête et que tout le reste, y compris la liste SELECT et le nom de la table, sont statiques. En fait, la majeure partie de la clause WHERE n'est même pas dynamique, seules les valeurs de recherche elles-mêmes. Vous ne pouvez pas ajouter dynamiquement les noms de colonnes de cette façon non plus. Cela pourrait certainement être construit, mais il faudrait que le moteur de recherche soit plus conscient du moteur de base de données qui est une boîte de Pandore que Microsoft ne voulait pas ouvrir. Imaginez un menu déroulant avec des noms de table tels que "Jobs", "People", "Employers" qu'un développeur naïf a construit. Au moment de la publication, cette valeur est utilisée pour SELECT * FROM. Une simple injection SQL serait tout ce qu'il faut pour passer à une autre table non répertoriée dans ce menu. Et passer quelque chose de vraiment bizarre pourrait très facilement jeter une erreur qui pourrait révéler quelque chose à propos de la base de données. Les requêtes paramétrées uniquement en valeur peuvent encore être interrompues mais la surface est beaucoup plus petite.

Certaines personnes ayant plusieurs préfixes de table utilisent des schémas, est-ce une option pour vous?

Questions connexes