sql-server - tuto - sql injection-numérique root me




Comment l'assainissement qui échappe aux guillemets simples peut-il être vaincu par injection SQL dans SQL Server? (4)

Avec quelques stipulations supplémentaires, votre approche ci-dessus n'est pas vulnérable à l'injection SQL. Le principal vecteur d'attaque à considérer est la contrebande SQL. La contrebande SQL se produit lorsque des caractères Unicode similaires sont traduits de manière inattendue (par exemple, en changeant en). Il existe plusieurs emplacements où une pile d'application peut être vulnérable à SQL Smuggling.

  • Le langage de programmation gère-t-il correctement les chaînes Unicode? Si la langue n'est pas unicode, elle peut mal identifier un octet dans un caractère Unicode comme une seule citation et l'échapper.

  • La bibliothèque de base de données client (par exemple ODBC, etc.) gère-t-elle correctement les chaînes Unicode? System.Data.SqlClient dans le framework .Net, mais qu'en est-il des anciennes bibliothèques de l'ère de Windows 95? Les bibliothèques ODBC tierces existent réellement. Que se passe-t-il si le pilote ODBC ne prend pas en charge Unicode dans la chaîne de requête?

  • La base de données gère-t-elle correctement l'entrée? Les versions modernes de SQL sont immunisées en supposant que vous utilisez N '', mais qu'en est-il de SQL 6.5? SQL 7.0? Je ne suis pas au courant de vulnérabilités particulières, mais ce n'était pas sur le radar pour les développeurs dans les années 1990.

  • Le buffer déborde? Une autre préoccupation est que la chaîne entre guillemets est plus longue que la chaîne d'origine. Dans quelle version de Sql Server était la limite de 2 Go pour l'entrée introduite? Avant cela, quelle était la limite? Sur les anciennes versions de SQL, que s'est-il passé lorsqu'une requête a dépassé la limite? Des limites existent-elles sur la longueur d'une requête du point de vue de la bibliothèque réseau? Ou sur la longueur de la chaîne dans le langage de programmation?

  • Y a-t-il des paramètres de langue qui affectent la comparaison utilisée dans la fonction Replace ()? .Net effectue toujours une comparaison binaire pour la fonction Replace (). Est-ce que ce sera toujours le cas? Que se passe-t-il si une future version de .NET prend en charge la substitution de ce comportement au niveau de l'app.config? Et si nous utilisions une expression rationnelle au lieu de Replace () pour insérer une seule citation? Les paramètres régionaux de l'ordinateur affectent-ils cette comparaison? Si un changement de comportement s'est produit, il n'est peut-être pas vulnérable à l'injection sql, mais il a peut-être modifié la chaîne par inadvertance en changeant un caractère uni-code qui ressemblait à un seul guillemet avant d'atteindre la base de données.

Ainsi, en supposant que vous utilisez la fonction System.String.Replace () en C # sur la version actuelle de .Net avec la bibliothèque intégrée SqlClient par rapport à une version actuelle (2005-2012) du serveur SQL, votre approche n'est pas vulnérable. Lorsque vous commencez à changer les choses, aucune promesse ne peut être faite. L'approche de requête paramétrée est l'approche correcte pour l'efficacité, la performance et (dans certains cas) pour la sécurité.

AVERTISSEMENT Les commentaires ci-dessus ne sont pas une approbation de cette technique. Il y a plusieurs autres très bonnes raisons pour lesquelles cette approche n'est pas la bonne pour générer du SQL. Cependant, en les détaillant est hors de la portée de cette question.

N'UTILISEZ PAS CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

N'UTILISEZ PAS CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

N'UTILISEZ PAS CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

Pour commencer, je suis bien conscient que les requêtes paramétrées sont la meilleure option, mais je demande ce qui rend la stratégie que je présente ci-dessous vulnérable. Les gens insistent sur le fait que la solution ci-dessous ne fonctionne pas, alors je cherche un exemple de pourquoi ce ne serait pas le cas.

Si le code SQL dynamique est construit en utilisant l'échappement suivant avant d'être envoyé à un serveur SQL, quel type d'injection peut vaincre cela?

string userInput= "N'" + userInput.Replace("'", "''") + "'"

Une question similaire a été répondue here , mais je ne crois pas que les réponses soient applicables ici.

Echapper de la citation unique avec un "\" n'est pas possible dans SQL Server.

Je crois que la contrebande SQL avec Unicode (décrite here ) serait contrecarrée par le fait que la chaîne produite est marquée comme Unicode par le N précédant la citation unique. Pour autant que je sache, il n'y a pas d'autres jeux de caractères que SQL Server traduirait automatiquement en une seule citation. Sans une seule citation non échappée, je ne crois pas que l'injection soit possible.

Je ne crois pas que String Truncation soit un vecteur viable non plus. SQL Server ne fera certainement pas la troncature puisque la taille maximale pour un nvarchar est de 2 Go selon microsoft . Une chaîne de 2 Go est irréalisable dans la plupart des situations, et impossible dans la mienne.

L'injection de second ordre pourrait être possible, mais est-ce possible si:

  1. Toutes les données entrant dans la base de données sont nettoyées en utilisant la méthode ci-dessus
  2. Les valeurs de la base de données ne sont jamais ajoutées en SQL dynamique (pourquoi le feriez-vous de toute façon, alors que vous pouvez simplement référencer la valeur de la table dans la partie statique d'une chaîne SQL dynamique?).

Je ne dis pas que c'est mieux que 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?


Il n'y a probablement pas de moyen sûr à 100% si vous faites une concaténation de chaînes. Ce que vous pouvez faire est d'essayer de vérifier le type de données pour chaque paramètre et si tous les paramètres passent une telle validation, alors allez-y avec l'exécution. Par exemple, si votre paramètre doit être de type int et que vous obtenez quelque chose qui ne peut pas être converti en int, il suffit de le rejeter.

Cela ne fonctionne pas si vous acceptez les paramètres nvarchar.

Comme d'autres l'ont déjà souligné. Le moyen le plus sûr est d'utiliser une requête paramétrée.


L'injection SQL peut se produire via unicode. Si l'application Web a une URL comme celle-ci:

http://mywebapp/widgets/?Code=ABC

qui génère SQL comme select * à partir de widgets où Code = 'ABC'

mais un pirate entre ça:

http://mywebapp/widgets/?Code=ABC%CA%BC;drop widgets de table--

le SQL ressemblera à select * des widgets où Code = 'ABC', drop widgets-- '

et SQL Server exécutera deux instructions SQL. Un pour faire le select et un pour faire la chute. Votre code convertit probablement le% CA% BC codé par url en unicode U02BC qui est une "lettre de modification apostrophe". La fonction Remplacer dans .Net ne traitera PAS cela comme une simple citation. Cependant, Microsoft SQL Server le traite comme une simple citation. Voici un exemple qui permettra probablement à SQL Injection:

string badValue = ((char)0x02BC).ToString();
badValue = badValue + ";delete from widgets--";
string sql = "SELECT * FROM WIDGETS WHERE ID=" + badValue.Replace("'","''");
TestTheSQL(sql);

L'injection SQL se produit si les entrées fournies par l'utilisateur sont interprétées comme des commandes. Ici, la commande signifie tout ce qui n'est pas interprété comme un littéral de type de données reconnu.

Maintenant, si vous utilisez l'entrée de l'utilisateur uniquement dans des littéraux de données, en particulier dans des littéraux de chaîne, l'entrée de l'utilisateur ne sera interprétée comme quelque chose de différent que des données de chaîne s'il est en mesure de quitter le contexte littéral. Pour la chaîne de caractères ou les littéraux de chaîne Unicode, c'est le guillemet simple qui entoure les données littérales tandis que le guillemet simple incorporé doit être représenté par deux guillemets simples.

Donc, pour quitter un contexte littéral de chaîne, il faudrait fournir un seul guillemet simple (sic) car deux guillemets simples sont interprétés comme des données littérales de chaîne et non comme le délimiteur de fin de chaîne littérale.

Par conséquent, si vous remplacez un guillemet simple dans les données fournies par l'utilisateur par deux guillemets simples, il sera impossible pour l'utilisateur de quitter le contexte littéral de la chaîne.





sanitization