Éviter l'injection SQL sans paramètres

109

Nous avons une autre discussion ici au travail sur l'utilisation de requêtes SQL paramétrées dans notre code. Nous avons deux côtés dans la discussion: moi et quelques autres qui disent que nous devrions toujours utiliser des paramètres pour se protéger contre les injections SQL et les autres gars qui ne pensent pas que c'est nécessaire. Au lieu de cela, ils veulent remplacer les apostrophes simples par deux apostrophes dans toutes les chaînes pour éviter les injections SQL. Nos bases de données exécutent toutes Sql Server 2005 ou 2008 et notre base de code fonctionne sur .NET Framework 2.0.

Laissez-moi vous donner un exemple simple en C #:

Je veux que nous utilisions ceci:

string sql = "SELECT * FROM Users WHERE Name=@name";
SqlCommand getUser = new SqlCommand(sql, connection);
getUser.Parameters.AddWithValue("@name", userName);
//... blabla - do something here, this is safe

Alors que les autres gars veulent faire ça:

string sql = "SELECT * FROM Users WHERE Name=" + SafeDBString(name);
SqlCommand getUser = new SqlCommand(sql, connection);
//... blabla - are we safe now?

Où la fonction SafeDBString est définie comme suit:

string SafeDBString(string inputValue) 
{
    return "'" + inputValue.Replace("'", "''") + "'";
}

Maintenant, tant que nous utilisons SafeDBString sur toutes les valeurs de chaîne dans nos requêtes, nous devrions être en sécurité. Droite?

Il y a deux raisons d'utiliser la fonction SafeDBString. Premièrement, c'est la façon dont cela a été fait depuis l'âge de pierre, et deuxièmement, il est plus facile de déboguer les instructions SQL puisque vous voyez la requête exacte qui est exécutée sur la base de données.

Donc alors. Ma question est de savoir s'il suffit vraiment d'utiliser la fonction SafeDBString pour éviter les attaques par injection SQL. J'ai essayé de trouver des exemples de code qui enfreignent cette mesure de sécurité, mais je n'en trouve aucun exemple.

Y a-t-il quelqu'un là-bas qui peut briser ça? Comment feriez-vous cela?

EDIT: Pour résumer les réponses à ce jour:

  • Personne n'a encore trouvé le moyen de contourner le SafeDBString sur Sql Server 2005 ou 2008. C'est bien, je pense?
  • Plusieurs réponses ont souligné que vous bénéficiez d'un gain de performances lors de l'utilisation de requêtes paramétrées. La raison en est que les plans de requête peuvent être réutilisés.
  • Nous convenons également que l'utilisation de requêtes paramétrées donne un code plus lisible et plus facile à maintenir
  • De plus, il est plus facile de toujours utiliser des paramètres que d'utiliser différentes versions de SafeDBString, des conversions de chaîne en nombre et des conversions de chaîne en date.
  • En utilisant des paramètres, vous obtenez une conversion de type automatique, ce qui est particulièrement utile lorsque nous travaillons avec des dates ou des nombres décimaux.
  • Et enfin: n'essayez pas de faire de la sécurité vous-même comme l'a écrit JulianR. Les fournisseurs de bases de données consacrent beaucoup de temps et d'argent à la sécurité. Il n'y a aucun moyen de faire mieux et aucune raison pour laquelle nous devrions essayer de faire leur travail.

Donc, même si personne n'a pu briser la sécurité simple de la fonction SafeDBString, j'ai eu beaucoup d'autres bons arguments. Merci!

Rune Grimstad
la source
16
Vos collègues sont bien loin de la base. Mettez-les au défi de trouver un seul document à l'appui de leur position. L'argument ex neolithos est ridicule, les choses changent, seule une personne coincée dans l'âge de pierre ne parviendrait pas à s'adapter.
annakata
1
Eh bien, au moins vos collègues se protègent contre UNE des différentes formes de piratage ... Sont-ils sûrs que toutes les requêtes paramétrées le font? (Je ne suis pas ...)
Arjan Einbu
1
Une seule vulnérabilité ne les convaincra pas. Si vous apportez plusieurs vulnérabilités (ce que vous demandez) et d'autres problèmes et indiquez un par un que les paramètres résoudront ce problème et que votre équipe devrait écrire des montagnes de code pour fournir une fraction des fonctionnalités, vous pouvez les convaincre. Bonne chance.
Robert Gowland
3
Même sans guillemets simples, vous pouvez toujours casser votre code avec la logique. Essayez d'utiliser le nom d'utilisateur "test OR 1 = 1" - vous obtenez toutes les lignes renvoyées plutôt que celle avec le test de nom d'utilisateur!
Bridge
1
Soupir. Je ne comprends vraiment pas comment nous, en tant qu'industrie, réussissons à continuer à tolérer ce genre de comportement non professionnel.
jeroenh

Réponses:

83

Je pense que la bonne réponse est:

N'essayez pas de faire de la sécurité vous-même . Utilisez la bibliothèque standard de confiance disponible pour ce que vous essayez de faire, plutôt que d' essayer de le faire vous-même. Quelles que soient les hypothèses que vous faites sur la sécurité, elles peuvent être incorrectes. Aussi sûre que puisse paraître votre propre approche (et elle semble au mieux fragile), il y a un risque que vous oubliez quelque chose et voulez-vous vraiment saisir cette chance en matière de sécurité?

Utilisez des paramètres.

JulianR
la source
Re «Utilisez n'importe quelle bibliothèque standard de confiance» - pouvez-vous en recommander une pour .NET? Peut-être plus d'un selon la base de données: SQLServer, MySQL, PostgreSQL? J'ai cherché SQL-sanitizer mais sans beaucoup de chance, j'ai donc été obligé d'implémenter le mien, du mieux que je peux (ce qui est sans doute loin d'être infaillible).
PSU
72

Et puis quelqu'un va et utilise "au lieu de". Les paramètres sont, IMO, la seule façon sûre d'aller.

Cela évite également de nombreux problèmes i18n avec les dates / nombres; quelle date est le 01/02/03? Combien vaut 123 456? Vos serveurs (serveur d'application et serveur de base de données) sont-ils d'accord les uns avec les autres?

Si le facteur de risque ne les convainc pas, qu'en est-il des performances? Le SGBDR peut réutiliser le plan de requête si vous utilisez des paramètres, ce qui améliore les performances. Il ne peut pas faire cela uniquement avec la chaîne.

Marc Gravell
la source
J'ai essayé les arguments de formatage et de performance, mais ils ne sont toujours pas convaincus.
Rune Grimstad
5
En fait, le serveur SQL peut réutiliser le plan de requête, que vous utilisiez des paramètres ou non. Je suis d'accord avec les autres arguments, mais dans la plupart des cas, l'argument de performance pour sql paramétré ne vole plus.
tnyfst
1
@tnyfst: il peut réutiliser le plan d'exécution lorsque la chaîne de requête change pour chaque combinaison de valeurs de paramètres? Je ne pensais pas que cela était possible.
John Saunders
4
Le plan de requête sera réutilisé si le texte de la requête est IDENTIQUE à un texte de requête antérieur. Donc, si vous envoyez la requête EXACT SAME deux fois, elle sera réutilisée. Cependant, si vous modifiez ne serait-ce qu'un espace ou une virgule ou quelque chose, un nouveau plan de requête devra être déterminé.
marc_s
1
@Marc: Je ne suis pas sûr que vous ayez tout à fait raison. Les hueristiques de mise en cache des serveurs SQL sont un peu bizarres. L'analyseur est capable d'identifier les constantes dans le texte et peut convertir la chaîne SQL en l'un des paramètres d'utilisation artificiellement. Il peut alors insérer dans le cache le texte de cette nouvelle requête paramétrée. Un SQL similaire ultérieur peut trouver sa version paramétrée dans le cache. Cependant, les versions paramétrées ne sont pas toujours utilisées avec les versions SQL d'origine mises en cache à la place, je soupçonne que SQL a un million de raisons liées aux performances pour choisir entre les deux approches.
AnthonyWJones
27

L'argument est un non-gagnant. Si vous parvenez à trouver une vulnérabilité, vos collègues changeront simplement la fonction SafeDBString pour en tenir compte, puis vous demanderont de prouver à nouveau qu'elle est dangereuse.

Étant donné que les requêtes paramétrées sont une meilleure pratique de programmation incontestée, la charge de la preuve devrait incomber à eux d'expliquer pourquoi ils n'utilisent pas une méthode à la fois plus sûre et plus performante.

Si le problème est de réécrire tout le code hérité, le compromis facile serait d'utiliser des requêtes paramétrées dans tout nouveau code et de refactoriser l'ancien code pour les utiliser lorsque vous travaillez sur ce code.

Je suppose que le véritable problème est la fierté et l'entêtement, et vous ne pouvez pas faire grand-chose de plus à ce sujet.

Matthew Christensen
la source
19

Tout d'abord, votre exemple pour la version "Remplacer" est incorrect. Vous devez mettre des apostrophes autour du texte:

string sql = "SELECT * FROM Users WHERE Name='" + SafeDBString(name) & "'";
SqlCommand getUser = new SqlCommand(sql, connection);

C'est donc une autre chose que les paramètres font pour vous: vous n'avez pas à vous soucier de savoir si une valeur doit être placée entre guillemets. Bien sûr, vous pouvez intégrer cela dans la fonction, mais vous devez ensuite ajouter beaucoup de complexité à la fonction: comment connaître la différence entre 'NULL' comme nul et 'NULL' comme une simple chaîne, ou entre un nombre et une chaîne qui contient juste beaucoup de chiffres. C'est juste une autre source de bogues.

Une autre chose est la performance: les plans de requête paramétrés sont souvent mieux mis en cache que les plans concaténés, ce qui économise peut-être au serveur une étape lors de l'exécution de la requête.

De plus, échapper des guillemets simples n'est pas suffisant. De nombreux produits DB autorisent d'autres méthodes pour échapper des caractères dont un attaquant pourrait tirer parti. Dans MySQL, par exemple, vous pouvez également échapper un guillemet simple avec une barre oblique inverse. Et donc la valeur de "nom" suivante ferait exploser MySQL avec juste la SafeDBString()fonction, car lorsque vous doublez le guillemet simple, le premier est toujours échappé par la barre oblique inverse, laissant le deuxième "actif":

x \ 'OU 1 = 1; -


De plus, JulianR soulève un bon point ci-dessous: N'essayez JAMAIS de faire des travaux de sécurité vous-même. Il est si facile de se tromper dans la programmation de sécurité de manière subtile qui semble fonctionner, même avec des tests approfondis. Puis le temps passe et un an plus tard, vous découvrez que votre système a été fissuré il y a six mois et que vous ne le saviez même pas jusqu'à ce moment-là.

Fiez-vous toujours autant que possible aux bibliothèques de sécurité fournies pour votre plateforme. Ils seront rédigés par des personnes qui font du code de sécurité pour gagner leur vie, bien mieux testés que ce que vous pouvez gérer, et gérés par le fournisseur si une vulnérabilité est découverte.

Joel Coehoorn
la source
5
La fonction de remplacement ajoute les apostrophes
Rune Grimstad
5
Ensuite, ce n'est qu'une autre source de bogues. Comment connaît-il la différence entre NULL en tant que valeur nulle et NULL en tant que chaîne de texte? Ou entre une entrée numérique et une chaîne qui contient juste des chiffres?
Joel Coehoorn
Bon point. Vous ne devez utiliser la fonction que pour les chaînes et éventuellement les dates, vous devez donc faire attention. C'est une raison de plus d'utiliser des paramètres! Yay!
Rune Grimstad
10

Alors je dirais:

1) Pourquoi essayez-vous de réimplémenter quelque chose qui est intégré? il est là, facilement disponible, facile à utiliser et déjà débogué à l'échelle mondiale. Si de futurs bogues y sont trouvés, ils seront corrigés et disponibles à tout le monde très rapidement sans que vous ayez à faire quoi que ce soit.

2) Quels processus sont en place pour garantir que vous ne manquerez un appel à SafeDBString? Le manquer à un seul endroit pourrait ouvrir toute une série de problèmes. Dans quelle mesure allez-vous regarder ces choses et considérez combien cet effort est gaspillé lorsque la bonne réponse acceptée est si facile à atteindre.

3) Dans quelle mesure êtes-vous certain d'avoir couvert tous les vecteurs d'attaque que Microsoft (l'auteur de la base de données et de la bibliothèque d'accès) connaît dans votre implémentation SafeDBString ...

4) Est-il facile de lire la structure du SQL? L'exemple utilise + concaténation, les paramètres ressemblent beaucoup à string.Format, qui est plus lisible.

En outre, il existe 2 façons de déterminer ce qui a été réellement exécuté: lancez votre propre fonction LogCommand, une fonction simple sans problèmes de sécurité , ou même regardez une trace SQL pour déterminer ce que la base de données pense réellement se passer.

Notre fonction LogCommand est simplement:

    string LogCommand(SqlCommand cmd)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine(cmd.CommandText);
        foreach (SqlParameter param in cmd.Parameters)
        {
            sb.Append(param.ToString());
            sb.Append(" = \"");
            sb.Append(param.Value.ToString());
            sb.AppendLine("\"");
        }
        return sb.ToString();
    }

Vrai ou faux, il nous donne les informations dont nous avons besoin sans problèmes de sécurité.

Jim T
la source
1
Il doit probablement faire face à un tas d'anciens programmeurs VBSCRIPT qui sont habitués à tout faire, y compris XML et SQL, par concaténation de chaînes. Ce seront des personnes qui ont peur de l'utilisation d'une API. Il n'y a rien à faire avec eux, du moins rien d'humain.
John Saunders
1
+1 pour l'élément n ° 2, à l'exception qu'il n'y a aucun moyen d'appliquer de vrais paramètres non plus.
Joel Coehoorn
7

Avec les requêtes paramétrées, vous obtenez plus qu'une protection contre l'injection SQL. Vous bénéficiez également d'un meilleur potentiel de mise en cache du plan d'exécution. Si vous utilisez le profileur de requêtes de serveur SQL, vous pouvez toujours voir le 'SQL exact qui est exécuté sur la base de données' afin que vous ne perdiez rien non plus en termes de débogage de vos instructions SQL.

Steve Willcock
la source
MySQL enregistre également les requêtes paramétrées avec des valeurs de paramètres interpolées.
Bill Karwin
5

J'ai utilisé les deux approches pour éviter les attaques par injection SQL et je préfère définitivement les requêtes paramétrées. Quand j'ai utilisé des requêtes concaténées, j'ai utilisé une fonction de bibliothèque pour échapper aux variables (comme mysql_real_escape_string) et je ne serais pas sûr d'avoir tout couvert dans une implémentation propriétaire (comme il semble que vous l'êtes aussi).

RougeBlueThing
la source
2
+1 parce que mysql_real_escape_string () échappe \ x00, \ x1a, \ n \ r 'et ". Il gère également les problèmes de jeu de caractères. La fonction naïve des collègues de l'OP ne fait rien de tout cela!
Bill Karwin
4

Vous ne pouvez pas effectuer facilement de vérification de type de l'entrée utilisateur sans utiliser de paramètres.

Si vous utilisez les classes SQLCommand et SQLParameter pour effectuer vos appels DB, vous pouvez toujours voir la requête SQL en cours d'exécution. Regardez la propriété CommandText de SQLCommand.

Je suis toujours un peu suspect de l'approche roll-your-own pour empêcher l'injection SQL lorsque les requêtes paramétrées sont si faciles à utiliser. Deuxièmement, ce n'est pas parce que «cela a toujours été fait de cette façon» que c'est la bonne façon de le faire.

Tim Scarborough
la source
3

Ce n'est sûr que si vous êtes assuré de passer une chaîne.

Que faire si vous ne passez pas une chaîne à un moment donné? Et si vous ne transmettez qu'un nombre?

http://www.mywebsite.com/profile/?id=7;DROP DATABASE DB

Deviendrait finalement:

SELECT * FROM DB WHERE Id = 7;DROP DATABASE DB
Joshcomley
la source
C'est soit une chaîne, soit un nombre. Une chaîne est échappée avec SafeDbString. Un nombre est un Int32 et il ne peut pas supprimer les bases de données.
Andomar
Les nombres sont plus faciles à gérer. Vous venez de convertir le paramètre en un int / float / peu importe avant de l'utiliser dans la requête. Le problème est lorsque vous devez accepter des données de chaîne.
Rune Grimstad
Andomar - si vous construisez simplement une instruction SQL à la main, alors le "type" prévu n'a pas d'importance, vous pouvez injecter SQL avec un nombre très, très facilement. Rune - Je pense que cela dépend beaucoup trop du développeur individuel pour se souvenir de toutes les nuances de la résolution manuelle de l'injection SQL. Si vous dites simplement "utiliser les paramètres", c'est très simple et ils ne peuvent pas se tromper.
joshcomley
@Andomar: Et NULL? Ou des chaînes qui ressemblent à des nombres?
Joel Coehoorn
2

J'utiliserais des procédures ou des fonctions stockées pour tout, donc la question ne se poserait pas.

Là où je dois mettre SQL dans le code, j'utilise des paramètres, ce qui est la seule chose qui a du sens. Rappelez aux dissidents qu'il existe des pirates informatiques plus intelligents qu'eux et mieux incités à casser le code qui tente de les déjouer. En utilisant des paramètres, ce n'est tout simplement pas possible, et ce n'est pas comme si c'était difficile.

John Saunders
la source
Ok, comment faire une injection SQL en utilisant des paramètres?
John Saunders
@Saunders: L'étape 1 consiste à trouver un bogue de dépassement de tampon dans la fonctionnalité de gestion des paramètres de votre base de données.
Brian
2
Vous en avez encore trouvé? Dans une base de données commerciale qui est pilonnée quotidiennement par des centaines de milliers de pirates informatiques? Une entreprise de logiciels connue pour ses poches très profondes? Vous seriez en mesure de citer le procès par son nom si cela était possible.
John Saunders
1
Bien sûr, si le SPROC utilise la concaténation et EXEC (au lieu de sp_ExecuteSQL), vous avez de nouveau des ennuis ... (je l'ai vu mal trop souvent pour l'ignorer ...)
Marc Gravell
2

Tout à fait d’accord sur les problèmes de sécurité.
Une autre raison d'utiliser des paramètres est l'efficacité.

Les bases de données compileront toujours votre requête et la mettront en cache, puis réutiliseront la requête en cache (ce qui est évidemment plus rapide pour les requêtes suivantes). Si vous utilisez des paramètres, même si vous utilisez des paramètres différents, la base de données réutilisera votre requête mise en cache car elle correspond en fonction de la chaîne SQL avant de lier les paramètres.

Si toutefois vous ne liez pas de paramètres, la chaîne SQL change à chaque requête (qui a des paramètres différents) et elle ne correspondra jamais à ce qui se trouve dans votre cache.

Darren Greaves
la source
2

Pour les raisons déjà données, les paramètres sont une très bonne idée. Mais nous détestons les utiliser car créer le paramètre et attribuer son nom à une variable pour une utilisation ultérieure dans une requête est une épave de tête à triple indirection.

La classe suivante encapsule le constructeur de chaînes que vous utiliserez couramment pour créer des requêtes SQL. Il vous permet d' écrire des requêtes paramétrées sans jamais avoir à créer de paramètre , vous pouvez donc vous concentrer sur le SQL. Votre code ressemblera à ceci ...

var bldr = new SqlBuilder( myCommand );
bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId, SqlDbType.Int);
//or
bldr.Append("SELECT * FROM CUSTOMERS WHERE NAME LIKE ").FuzzyValue(myName, SqlDbType.NVarChar);
myCommand.CommandText = bldr.ToString();

La lisibilité du code, j'espère que vous en conviendrez, est grandement améliorée et le résultat est une requête paramétrée appropriée.

La classe ressemble à ceci ...

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace myNamespace
{
    /// <summary>
    /// Pour le confort et le bonheur, cette classe remplace StringBuilder pour la construction
    /// des requêtes SQL, avec l'avantage qu'elle gère la création des paramètres via la méthode
    /// Value().
    /// </summary>
    public class SqlBuilder
    {
        private StringBuilder _rq;
        private SqlCommand _cmd;
        private int _seq;
        public SqlBuilder(SqlCommand cmd)
        {
            _rq = new StringBuilder();
            _cmd = cmd;
            _seq = 0;
        }
        //Les autres surcharges de StringBuilder peuvent être implémenté ici de la même façon, au besoin.
        public SqlBuilder Append(String str)
        {
            _rq.Append(str);
            return this;
        }
        /// <summary>
        /// Ajoute une valeur runtime à la requête, via un paramètre.
        /// </summary>
        /// <param name="value">La valeur à renseigner dans la requête</param>
        /// <param name="type">Le DBType à utiliser pour la création du paramètre. Se référer au type de la colonne cible.</param>
        public SqlBuilder Value(Object value, SqlDbType type)
        {
            //get param name
            string paramName = "@SqlBuilderParam" + _seq++;
            //append condition to query
            _rq.Append(paramName);
            _cmd.Parameters.Add(paramName, type).Value = value;
            return this;
        }
        public SqlBuilder FuzzyValue(Object value, SqlDbType type)
        {
            //get param name
            string paramName = "@SqlBuilderParam" + _seq++;
            //append condition to query
            _rq.Append("'%' + " + paramName + " + '%'");
            _cmd.Parameters.Add(paramName, type).Value = value;
            return this; 
        }

        public override string ToString()
        {
            return _rq.ToString();
        }
    }
}
bbsimonbb
la source
1

Depuis le temps très court que j'ai eu pour enquêter sur les problèmes d'injection SQL, je peux voir que rendre une valeur `` sûre '' signifie également que vous fermez la porte à des situations où vous pourriez réellement vouloir des apostrophes dans vos données - qu'en est-il du nom de quelqu'un , par exemple O'Reilly.

Cela laisse les paramètres et les procédures stockées.

Et oui, vous devriez toujours essayer d'implémenter le code de la meilleure façon que vous connaissez maintenant - pas seulement comme cela a toujours été fait.

quamrana
la source
Les doubles apostrophes seront traduites par le serveur sql en une seule apostrophe, donc O'Reilly serait traduit en Name = 'O''Reilly'
Rune Grimstad
Existe-t-il donc une fonction correspondante pour supprimer les apostrophes lorsque l'utilisateur souhaite voir ses données?
quamrana
Ce n'est pas nécessaire. La séquence d'échappement permet à l'analyseur de voir un guillemet simple plutôt que la fin de la chaîne. Lors de l'analyse, il est considéré ''comme un littéral ', donc votre chaîne sera vue en interne comme la séquence de caractères O'Reilly. C'est ce que la base de données va stocker, récupérer, comparer, etc. Si vous voulez montrer à l'utilisateur ses données après que vous les ayez échappées, conservez une copie de la chaîne non échappée à côté.
cHao
1

Voici quelques articles qui pourraient vous aider à convaincre vos collègues.

http://www.sommarskog.se/dynamic_sql.html

http://unixwiz.net/techtips/sql-injection.html

Personnellement, je préfère ne jamais permettre à un code dynamique de toucher ma base de données, exigeant que tous les contacts se fassent via SP (et non un qui utilise SQl dynamique). Cela signifie que rien d'autre que ce que j'ai donné aux utilisateurs l'autorisation de faire ne peut être fait et que les utilisateurs internes (à l'exception des très rares utilisateurs disposant d'un accès en production à des fins d'administration) ne peuvent pas accéder directement à mes tables et créer des ravages, voler des données ou commettre une fraude. Si vous exécutez une application financière, c'est la solution la plus sûre.

HLGEM
la source
1

Il peut être cassé, mais les moyens dépendent des versions / correctifs exacts, etc.

Celui qui a déjà été évoqué est le bug de débordement / troncature qui peut être exploité.

Un autre moyen futur serait de trouver des bogues similaires à d'autres bases de données - par exemple, la pile MySQL / PHP a subi un problème d'échappement car certaines séquences UTF8 pourraient être utilisées pour manipuler la fonction de remplacement - la fonction de remplacement serait amenée à introduire les caractères d'injection.

A la fin de la journée, le mécanisme de sécurité de remplacement repose sur prévu , mais pas l' intention . Étant donné que la fonctionnalité n'était pas l'objectif prévu du code, il y a de fortes chances que certaines bizarreries découvertes cassent la fonctionnalité attendue.

Si vous avez beaucoup de code hérité, la méthode replace peut être utilisée comme un palliatif pour éviter de longues réécritures et tests. Si vous écrivez un nouveau code, il n'y a aucune excuse.

David
la source
1

Utilisez toujours des requêtes paramétrées lorsque cela est possible. Parfois, même une simple entrée sans l'utilisation de caractères étranges peut déjà créer une injection SQL si elle n'est pas identifiée comme une entrée pour un champ dans la base de données.

Alors laissez simplement la base de données faire son travail d'identification de l'entrée elle-même, sans oublier qu'elle évite également beaucoup de problèmes lorsque vous devez insérer des caractères étranges qui autrement seraient échappés ou modifiés. Il peut même économiser un temps d'exécution précieux à la fin pour ne pas avoir à calculer l'entrée.

VulstaR
la source
1

Je n'ai vu aucun autre répondeur aborder ce côté du «pourquoi le faire soi-même est mauvais», mais considérez une attaque de troncature SQL .

Il existe également la fonction QUOTENAMET-SQL qui peut être utile si vous ne pouvez pas les convaincre d'utiliser des paramètres. Il attrape beaucoup (tous?) Des problèmes de qoute échappés.

JasonRShaver
la source
1

2 ans plus tard , j'ai récidivé ... Toute personne qui trouve des paramètres une douleur est la bienvenue pour essayer mon VS Extension, QueryFirst . Vous éditez votre demande dans un vrai fichier .sql (Validation, Intellisense). Pour ajouter un paramètre, il vous suffit de le saisir directement dans votre SQL, en commençant par le '@'. Lorsque vous enregistrez le fichier, QueryFirst génère des classes wrapper pour vous permettre d'exécuter la requête et d'accéder aux résultats. Il recherchera le type de base de données de votre paramètre et le mappera à un type .net, que vous trouverez en entrée des méthodes Execute () générées. Ça ne pourrait pas être plus simple. Le faire de la bonne manière est radicalement plus rapide et plus facile que de le faire de toute autre manière, et créer une vulnérabilité d'injection SQL devient impossible, ou du moins perversement difficile. Il existe d'autres avantages majeurs, comme la possibilité de supprimer des colonnes dans votre base de données et de voir immédiatement les erreurs de compilation dans votre application.

avertissement légal: j'ai écrit QueryFirst

bbsimonbb
la source
0

Voici quelques raisons d'utiliser des requêtes paramétrées:

  1. Sécurité - La couche d'accès à la base de données sait comment supprimer ou échapper des éléments qui ne sont pas autorisés dans les données.
  2. Séparation des préoccupations - Mon code n'est pas responsable de la transformation des données dans un format que la base de données aime.
  3. Pas de redondance - je n'ai pas besoin d'inclure un assembly ou une classe dans chaque projet qui effectue le formatage / échappement de cette base de données; il est intégré à la bibliothèque de classes.
Powerlord
la source
0

Il y avait peu de vulnérabilités (je ne me souviens plus de quelle base de données il s'agissait) liées au dépassement de tampon de l'instruction SQL.

Ce que je veux dire, c'est que SQL-Injection est plus que simplement "échapper à la citation", et vous n'avez aucune idée de ce qui va suivre.

Dennis C
la source
0

Une autre considération importante est le suivi des données échappées et non échappées. Il y a des tonnes et des tonnes d'applications, Web et autres, qui ne semblent pas suivre correctement le moment où les données sont en brut-Unicode, & -encodées, formatées en HTML, et cetera. Il est évident qu'il deviendra difficile de savoir quelles chaînes sont ''codées et lesquelles ne le sont pas.

C'est aussi un problème lorsque vous finissez par changer le type d'une variable - peut-être que c'était un entier, mais maintenant c'est une chaîne. Maintenant vous avez un problème.

Paul Fisher
la source