Pour commencer, je suis bien conscient que les requêtes paramétrées sont la meilleure option, mais je demande ce qui rend vulnérable la stratégie que je présente ci-dessous. Les gens insistent sur le fait que la solution ci-dessous ne fonctionne pas, alors je cherche un exemple de pourquoi elle ne fonctionnerait pas.
Si le SQL dynamique est construit dans un code utilisant l'échappement suivant avant d'être envoyé à un serveur SQL, quel type d'injection peut vaincre cela ?
string userInput= "N'" + userInput.Replace("'", "''") + "'"
Il a été répondu à une question similaire aquí mais je ne crois pas qu'aucune des réponses soit applicable ici.
L'échappement du guillemet simple par un "\" n'est pas possible dans le serveur SQL.
Je crois Contrebande de SQL avec Unicode (souligné aquí ) serait contrecarrée par le fait que la chaîne produite est marquée comme Unicode par le N qui précède le guillemet simple. Pour autant que je sache, il n'y a pas d'autres jeux de caractères que SQL Server traduirait automatiquement en guillemets simples. Sans guillemet simple non encodé, je ne pense pas que l'injection soit possible.
Je ne crois pas Troncature de la chaîne n'est pas non plus un vecteur viable. SQL Server ne fera certainement pas la troncature puisque la taille maximale d'un fichier de type nvarchar
est de 2GB selon microsoft . Une chaîne de 2 Go est irréalisable dans la plupart des situations, et impossible dans la mienne.
Injection de second ordre pourrait être possible, mais est-ce possible si :
- Toutes les données qui entrent dans la base de données sont nettoyées en utilisant la méthode ci-dessus.
- Les valeurs de la base de données ne sont jamais ajoutées au SQL dynamique (pourquoi le feriez-vous de toute façon, alors que vous pouvez simplement faire référence à la valeur de la table dans la partie statique de toute chaîne SQL dynamique).
Je ne veux pas dire que c'est mieux ou une alternative à l'utilisation de requêtes paramétrées, mais je veux savoir comment ce que j'ai décrit est vulnérable. Des idées ?
1 votes
Non. Tu es toujours sensible aux attaques dans la forme :
"SELECT * FROM MyTable WHERE Field = " + userInput
quanduserInput
es0; DROP TABLE OhNo;
.15 votes
Cela n'a aucun sens. Dans l'exemple ci-dessus, votre entrée utilisateur serait nettoyée en N'0 ; DROP TABLE OhNo;' avant d'être exécutée.
6 votes
Ceci ne sert qu'à assainir les variables de type chaîne. Des éléments comme "int" n'ont pas besoin d'être nettoyés s'ils sont convertis en int avant d'être ajoutés à la requête. Quoi qu'il en soit, je ne demande que la désinfection des chaînes de caractères pour le moment. Aussi, il n'y a pas besoin d'être grossier ici. Si vous pouvez penser à une façon dont ce n'est pas sûr, je serais ravi de le savoir.
0 votes
Ok, que diriez-vous de userinput = "test' ; drop table ohno ; print '"
2 votes
Les guillemets simples sont transformés en deux guillemets simples (c'est ainsi que l'on échappe les guillemets simples), ce qui les rend inoffensifs. Votre entrée utilisateur devient alors : N'test'' ; drop table ohno ; print ''' ce qui est inoffensif.
0 votes
La question n'est pas intéressante car votre approche ne présente aucun avantage par rapport à l'utilisation d'une requête paramétrée. Il y a plusieurs inconvénients, notamment des compilations excessives et un gonflement du cache du plan.
0 votes
De plus, si la colonne de la table n'est pas unicode, vous empêcherez l'utilisation d'index sur ces colonnes en raison du casting implicite.
0 votes
Il n'existe absolument aucun scénario dans lequel vous seriez en mesure d'effectuer un assainissement complet de l'entrée et de ne pas être en mesure d'écrire des requêtes paramétrées. Si vous connaissez suffisamment le schéma de la base de données pour être capable d'assainir l'entrée vous-même, alors vous en savez assez pour écrire une requête paramétrée. Le choix évident est la requête paramétrée car le code résultant sera plus propre, moins sujet aux erreurs et aux problèmes de sécurité accidentels lorsque le responsable du code n'est pas prudent.
4 votes
Ne serait-ce pas un bon choix lorsque le SQL dynamique est inévitable ?
0 votes
Il existe des raisons pour lesquelles l'analyse littérale est nécessaire. Imaginez que vous traitiez une liste de chaînes de caractères de longueur inconnue et que vous ayez besoin de générer une instruction SQL pour le faire : SELECT x from y where text in ('A', 'B', 'C', ...) La seule façon d'écrire cette instruction de manière dynamique et efficace est d'utiliser des littéraux. La méthode de GBleaney est sûre, il semble qu'il écrive du code C# qui est unicode, le pilote .Net est unicode et il n'y a rien de mal à cela.
0 votes
@Rob Je peux toujours créer le sql avec les ? requis pour les paramètres et fournir les paramètres séparément. D'autant plus que je dois de toute façon effectuer une analyse syntaxique puisque la longueur d'une clause "in" est limitée dans de nombreux SGBDR.
0 votes
Oui, vous pouvez créer une chaîne de requête dynamique et placer des marqueurs de paramètres à la place des littéraux.
2 votes
@StrayCatDBA C'est une question intéressante lorsque le code en question a plus de 25 ans et qu'il est difficile de le moderniser avec des requêtes paramétrées.