Comment un assainissement qui échappe à des guillemets simples peut-il être vaincu par L'injection SQL dans SQL Server?

Pour commencer, je suis bien conscient que les requêtes paramétrées sont la meilleure option, mais je me demande ce qui rend la stratégie que je présente ci-dessous vulnérables. Les gens insistent sur le fait que la solution ci-dessous ne fonctionne pas, donc je suis à la recherche d'un exemple de pourquoi elle ne fonctionnerait pas.

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

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

une question similaire a été répondu ici , mais je ne crois pas que les réponses s'appliquent ici.

échapper à la citation simple avec un "" N'est pas possible dans SQL Server.

je crois SQL Contrebande avec Unicode (indiqué ici ) serait contrarié par le fait que la chaîne est produit est marqué comme Unicode par le N précédant l'apostrophe. Autant que je sache, il n'y a pas d'autres jeux de caractères SQL Server traduirait automatiquement en un seul devis. Sans une simple citation, Je ne crois pas que l'injection soit possible.

je ne crois pas la Troncature de Chaîne est viable vecteur. SQL Server ne fera certainement pas le tronçonnage puisque la taille max 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.

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 aseptisées en utilisant la méthode ci-dessus
  2. Les valeurs
  3. de la base de données ne sont jamais ajoutées dans le SQL dynamique (pourquoi le feriez-vous de toute façon, alors que vous pouvez simplement référencer la valeur de table dans la partie statique de n'importe quelle chaîne de SQL dynamique?).

Je ne suggère pas que c'est meilleure 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?

59
demandé sur Community 2013-03-21 04:31:08

6 réponses

il y a quelques cas où cette fonction d'échappement échouera. La plus évidente est lorsqu'une seule citation n'est pas utilisée:

string table= "\"" + table.Replace("'", "''") + "\""
string var= "`" + var.Replace("'", "''") + "`"
string index= " " + index.Replace("'", "''") + " "
string query = "select * from `"+table+"` where name=\""+var+"\" or id="+index

dans ce cas, vous pouvez" vous évader " en utilisant un double devis, un back-tick. Dans le dernier cas, il n'y a rien à "casser", donc vous pouvez simplement écrire 1 union select password from users-- ou n'importe quelle charge sql que l'attaquant désire.

la prochaine condition où cette fonction d'échappement échouera est si une sous-chaîne est prise après que la chaîne est échappée (et Oui j'ai trouvé des vulnérabilités comme ceci dans la nature):

string userPassword= userPassword.Replace("'", "''")
string userName= userInput.Replace("'", "''")
userName = substr(userName,0,10)
string query = "select * from users where name='"+userName+"' and password='"+userPassword+"'";

Dans ce cas, un nom d'utilisateur de abcdefgji' sera transformé en abcdefgji'' par la fonction d'échappement, puis transformé en abcdefgji' en prenant la sous-chaîne. Ceci peut être exploité en définissant la valeur du mot de passe à n'importe quelle instruction sql, dans ce cas or 1=1-- serait interprété comme sql et le nom d'utilisateur serait interprété comme abcdefgji'' and password= . La requête résultante est la suivante:

select * from users where name='abcdefgji'' and password=' or 1=1-- 

T-SQL et autres techniques avancées d'injection sql déjà mentionnées. Advanced SQL Injection In SQL Server Applications est un excellent papier et vous devriez le lire si vous n'avez pas déjà.

La question finale est de l'unicode des attaques. Cette classe de vulnérabilités se produit parce que la fonction escape n'est pas au courant de l'encodage mulit-byte, et cela peut être utilisé par un attaquant pour "consommer" le caractère d'échappement . Préparer un " N " à la chaîne n'aidera pas, car cela n'affecte pas la valeur des caractères multi-octets plus tard dans la chaîne. Cependant, ce type d'attaque est très rare car la base de données doit être configurée pour accepter les chaînes unicode GBK (et je ne suis pas sûr que MS-SQL puisse le faire).

l'injection de code de Second ordre est encore possible, ce motif d'attaque est créé par confiance sources de données contrôlées par l'attaquant. Escape est utilisé pour représenter les caractères de contrôle comme leur caractère littéral. Si le développeur oublie d'échapper à une valeur obtenue à partir d'un select et utilise ensuite cette valeur dans une autre requête alors bam l'attaquant aura un caractère littéral simple citation à leur disposition.

tout tester, ne rien croire.

34
répondu rook 2017-08-06 07:19:02

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 de SQL se produit lorsque des caractères unicodes similaires sont traduits d'une manière inattendue (par exemple "passer à"). Il existe plusieurs endroits où une pile d'application pourrait être vulnérable à la contrebande SQL.

  • le langage de programmation gère-t-il les chaînes unicode? de manière appropriée? si le langage n'est pas conscient d'unicode, il peut mal identifier un octet dans un caractère unicode comme une simple citation et l'échapper.

  • la bibliothèque de la base de données client (par exemple ODBC, etc) gère-t-elle les chaînes unicode de manière appropriée? Système .Données.SqlClient dans le framework .Net le fait, mais qu'en est-il des anciennes bibliothèques de l'ère windows 95? Les bibliothèques ODBC tiers existent effectivement. Que se passe-t-il si le pilote ODBC ne supporte pas unicode dans la chaîne de requête?

  • le DB gère-t-il 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 d'aucune vulnérabilité particulière, mais ce n'était pas sur le radar pour les développeurs dans les années 1990.

  • dépassements de la mémoire Tampon? une autre préoccupation est que le la chaîne Citée est plus longue que la chaîne originale. Dans quelle version de Sql Server la limite de 2 Go pour l'entrée a-t-elle été introduite? Avant ça, quelle était la limite? Sur les anciennes versions de SQL, que s'est-il passé quand une requête a dépassé la limite? Existe-t-il des limites quant à 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 linguistiques qui affectent la comparaison utilisée dans la fonction de remplacement ()? .Net effectue toujours une comparaison binaire pour la fonction Replace (). Sera toujours le cas? Que se passe-t-il si une future version de .NET supporte la suppression de ce comportement dans l'application?config? Que faire si nous avons utilisé un regexp au lieu de Replace() pour insérer un seul devis? L'ordinateur, les paramètres régionaux affectent cette comparaison? Si un changement de comportement se produisait, il pourrait ne pas être vulnérable à l'injection sql, cependant, il peut avoir j'ai modifié la chaîne de caractères par inadvertance en changeant un caractère uni-code qui ressemblait à une simple citation en une seule citation avant qu'elle n'atteigne la base de données.

donc, en supposant que vous utilisez le système.Chaîne.Remplacer () la fonction en C# sur la version actuelle de .Net avec la bibliothèque SqlClient intégrée contre une version actuelle (2005-2012) de SQL server, alors votre approche n'est pas vulnérable. Comme vous commencer à changer les choses, alors aucune promesse ne peut être faite. Le requête paramétrée approche est la bonne approche pour l'efficacité, de performance, et (dans certains cas) pour plus de 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 c'est la mauvaise approche pour générer SQL. Toutefois, les détailler dépasse le cadre de cette question.

NE PAS UTILISER CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

NE PAS UTILISER CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

NE PAS UTILISER CETTE TECHNIQUE POUR UN NOUVEAU DÉVELOPPEMENT.

16
répondu StrayCatDBA 2013-03-29 19:18:47

utiliser les paramètres de requête est meilleur, plus facile et plus rapide que d'échapper à des guillemets.


concernant votre commentaire, je vois que vous avez reconnu la paramétrisation, mais elle mérite d'être soulignée. Pourquoi voudriez-vous d'utiliser échapper lorsque vous pouvez paramétrer?

In Advanced SQL Injection In SQL Server Applications , rechercher le mot "replace" dans le texte, et à partir de ce point sur lire quelques exemples où les développeurs ont par inadvertance permis des attaques par injection SQL même après avoir échappé à l'entrée de l'utilisateur.


il y a un cas de bordure où le fait d'échapper à des guillemets avec \ entraîne une vulnérabilité, parce que le \ devient la moitié d'un caractère valide de plusieurs octets dans certains jeux de caractères. Mais cela ne s'applique pas à votre cas puisque \ n'est pas le personnage fuyant.

comme d'autres l'ont souligné vous pouvez également ajouter du contenu dynamique à votre SQL pour autre chose qu'une chaîne de caractères littérale ou une date littérale. Les identificateurs de Table ou de colonne sont délimités par " en SQL, ou [ ] en Microsoft/Sybase. Les mots-clés SQL n'ont évidemment pas de délimiteurs. Pour ces cas, je recommande liste blanche les valeurs à interpoler.

la ligne de fond est que l'évasion est une défense efficace, si vous pouvez vous assurer que vous faire de manière cohérente. C'est le risque: celui de l'équipe de développeurs sur votre demande pourrait omettre une étape et faire de la chaîne d'interpolation mal.

bien sûr, il en va de même pour d'autres méthodes, comme la paramétrisation. Ils ne sont efficaces que si vous les faites avec constance. Mais je trouve qu'il est plus facile d'utiliser les paramètres plus rapidement que de trouver le bon type d'échappement. Et les développeurs sont plus susceptibles d'utiliser une méthode est pratique et ne les ralentit pas.

9
répondu Bill Karwin 2013-03-30 14:15:36

SQL injection se produire si l'utilisateur a fourni des intrants sont interprétées comme des commandes. Ici commande signifie Tout ce qui n'est pas interprété comme un reconnu type de données littéral.

maintenant, si vous utilisez l'entrée de l'utilisateur uniquement dans les littérales de données, spécifiquement seulement dans les littérales de chaîne, l'entrée de l'utilisateur ne serait interprété comme quelque chose de différent que des données de chaîne si elle serait en mesure de quitter le contexte littéral de chaîne. Pour chaîne de caractères ou Unicode les littéraux de chaîne, c'est le guillemet simple qui entoure les données littérales tout intégré guillemet simple besoin d'être représenté avec deux guillemets simples.

ainsi, pour laisser un contexte littéral à une chaîne de caractères, il faudrait fournir un seul guillemet (sic) puisque deux guillemets simples sont interprétés comme des données littérales de chaîne de caractères et non comme le délimiteur de fin littérale de chaîne de caractères.

donc si vous remplacez un seul guillemet dans le données fournies par les utilisateurs par deux guillemets simples, il sera impossible pour l'utilisateur de quitter la chaîne de caractères littérale contexte.

4
répondu Gumbo 2013-03-21 06:27:00
L'Injection

SQL peut se faire via unicode. Si l'application web a une URL comme celle-ci:

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

qui génère comme SQL sélectionnez * à partir des widgets où Code = 'ABC'

mais un hacker entre ceci:

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

le SQL ressemblera à sélectionner * à partir des widgets où Code = 'ABC’; DROP TABLE widgets-- '

et SQL Server exécutera deux instructions SQL. Pour faire la sélection et à la baisse. Votre code convertit probablement le %CA % BC encodé en url en unicode U02BC qui est un"modificateur de lettre apostrophe". La fonction Replace dans .Net ne traitera pas cela comme un devis unique. Cependant Microsoft SQL Server le traite comme un devis simple. Voici un exemple qui permettra probablement L'Injection SQL:

string badValue = ((char)0x02BC).ToString();
badValue = badValue + ";delete from widgets--";
string sql = "SELECT * FROM WIDGETS WHERE ID=" + badValue.Replace("'","''");
TestTheSQL(sql);
3
répondu Rob Kraft 2015-07-30 14:24:37

il n'y a probablement aucun moyen sûr à 100% Si vous faites la concaténation de chaîne. 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 de l'avant 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, alors rejetez-le.

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

comme d'autres l'ont déjà souligné hors. La façon la plus sûre est d'utiliser la requête paramétrée.

2
répondu George Wesley 2013-03-21 10:14:47