2008-09-30 9 views
3

Nous essayons de mettre à jour notre moteur de recherche asp classique pour le protéger de l'injection SQL. Nous avons une fonction VB 6 qui construit une requête dynamiquement en concaténant une requête ensemble en fonction des différents paramètres de recherche. Nous avons converti cela en une procédure stockée en utilisant SQL dynamique pour tous les paramètres, sauf pour les mots-clés.Dynamic SQL - Requête de recherche - Variable Nombre de mots-clés

Le problème avec les mots-clés est qu'il y a un nombre de mots variables fourni par l'utilisateur et nous voulons rechercher plusieurs colonnes pour chaque mot-clé. Puisque nous ne pouvons pas créer un paramètre distinct pour chaque mot clé, comment pouvons-nous créer une requête sécurisée?

Exemple:

@CustomerId AS INT 
@Keywords AS NVARCHAR(MAX) 

@sql = 'SELECT event_name FROM calendar WHERE customer_id = @CustomerId ' 

--(loop through each keyword passed in and concatenate) 

@sql = @sql + 'AND (event_name LIKE ''%' + @Keywords + '%'' OR event_details LIKE ''%' + @Keywords + '%'')' 

EXEC sp_executesql @sql N'@CustomerId INT, @CustomerId = @CustomerId 

Quelle est la meilleure façon de gérer et de maintenir cette protection contre l'injection SQL?

Répondre

3

Vous n'aimez peut-être pas entendre cela, mais il est peut-être préférable de revenir à la construction dynamique de votre requête SQL dans le code avant d'émettre sur la base de données. Si vous utilisez des espaces réservés de paramètres dans la chaîne SQL, vous bénéficiez de la protection contre les attaques par injection SQL.

Exemple:

string sql = "SELECT Name, Title FROM Staff WHERE [email protected]"; 
using (SqlCommand cmd = new SqlCommand(sql)) 
{ 
    cmd.Parameters.Add("@UserId", SqlType.VarChar).Value = "smithj"; 

Vous pouvez construire la chaîne SQL en fonction de l'ensemble des colonnes dont vous avez besoin pour interroger et puis ajoutez les valeurs des paramètres une fois que la chaîne est terminée. C'est un peu pénible à faire, mais je pense que c'est beaucoup plus facile que d'avoir vraiment compliqué TSQL qui décompose beaucoup de permutations possibles d'entrées possibles.

+0

+1 cette approche évitera le problème échappe entièrement –

1

Vous avez 3 options ici.

  1. Utilisez un function that converts lists tables et rejoignez-y. Donc, vous aurez quelque chose comme ça.

    SELECT * 
    FROM calendar c 
        JOIN dbo.fnListToTable(@Keywords) k 
         ON c.keyword = k.keyword 
    
  2. ont un ensemble fixe de params, et seulement permettre au maximum de mots-clés N à rechercher sur

    CREATE PROC spTest 
    @Keyword1 varchar(100), 
    @Keyword2 varchar(100), 
    .... 
    
  3. Ecrire une fonction de chaîne échapper à TSQL et échapper à vos mots clés.

0
  • À moins que vous en avez besoin, vous pouvez simplement dépouiller tout caractère qui ne figure pas dans [a-zA-Z] - la plupart de ces choses ne seront pas dans les recherches et vous ne devriez pas être en mesure de être injecté de cette façon, ni vous devez vous soucier de mots-clés ou quelque chose comme ça. Si vous autorisez des citations, cependant, vous devrez être plus prudent.

  • similaires à # 1 de sambo99, vous pouvez insérer les mots-clés dans une table temporaire ou variable table et y joindre (même en utilisant des jokers) sans danger d'injection:

Ce n'est pas vraiment dynamique :

SELECT DISTINCT event_name 
FROM calendar 
INNER JOIN #keywords 
    ON event_name LIKE '%' + #keywords.keyword + '%' 
    OR event_description LIKE '%' + #keywords.keyword + '%' 
  • Vous pouvez effectivement générer un SP avec un grand nombre de paramètres au lieu de coder manuellement (définir les paramètres par défaut à « » ou NULL en fonction de vos préférences en coder vos recherches).Si vous aviez besoin de plus de paramètres, il serait simple d'augmenter le nombre de paramètres générés.

  • Vous pouvez déplacer la recherche vers un index de texte intégral en dehors de la base de données comme Lucene, puis utiliser les résultats Lucene pour extraire les lignes de base de données correspondantes.

0

Vous pouvez essayer ceci:

SELECT * FROM [tablename] WHERE LIKE % +keyword% 
Questions connexes