Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment nettoyer (empêcher l'injection SQL) SQL dynamique dans SQL Server ?

Je crois qu'il y a trois cas différents dont vous devez vous soucier :

  • chaînes (tout ce qui nécessite des guillemets) :'''' + replace(@string, '''', '''''') + ''''
  • noms (tout ce qui n'est pas autorisé entre guillemets) :quotename(@string)
  • choses qui ne peuvent pas être citées :cela nécessite une liste blanche

Remarque  :Tout dans une variable chaîne (char , varchar , nchar , nvarchar , etc.) provenant de sources contrôlées par l'utilisateur doivent utiliser l'une des méthodes ci-dessus. Cela signifie que même les éléments que vous pensez être des nombres sont entre guillemets s'ils sont stockés dans des variables de chaîne.

Pour plus de détails, consultez le Microsoft Magazine (Lien obsolète :2016-10-19) .

Voici un exemple utilisant les trois méthodes :

EXEC 'SELECT * FROM Employee WHERE Salary > ''' +
     REPLACE(@salary, '''', '''''') +   -- replacing quotes even for numeric data
     ''' ORDER BY ' + QUOTENAME(@sort_col) + ' ' +  -- quoting a name
     CASE @sort_dir WHEN 'DESC' THEN 'DESC' END     -- whitelisting

Notez également qu'en effectuant toutes les opérations de chaîne en ligne dans le EXEC déclaration il n'y a pas de problème avec les problèmes de troncature. Si vous affectez les résultats intermédiaires à des variables, vous devez assurez-vous que les variables sont suffisamment grandes pour contenir les résultats. Si vous faites SET @result = QUOTENAME(@name) vous devez définir @result contenir au moins 258 (2 * 128 + 2) caractères. Si vous faites SET @result = REPLACE(@str, '''', '''''') vous devez définir @result être le double de la taille de @str (supposons que chaque caractère dans @str peut être une citation). Et bien sûr, la variable de chaîne contenant l'instruction SQL finale doit être suffisamment grande pour contenir tout le SQL statique ainsi que toutes les variables de résultat.