83 votes

Les paramètres sont-ils vraiment suffisants pour empêcher les injections SQL?

J'ai enseigné à mes collègues et ici, sur la DONC sur la bonté de l'utilisation de paramètres dans les requêtes SQL, en particulier dans .NET applications. J'ai même été jusqu'à leur promettre que de donner de l'immunité contre les attaques par injection SQL.

Mais je commence à me demander si c'est vraiment vrai. Sont-ils connus des attaques par injection SQL qui sera réussie contre une requête paramétrée? Vous pouvez par exemple envoyer une chaîne de caractères qui provoque un dépassement de tampon sur le serveur?

Il y a bien sûr d'autres considérations à faire pour s'assurer qu'une application web qui est sûr (comme la désinfection de la saisie de l'utilisateur et ce genre de trucs) mais maintenant, je pense à des injections SQL. Je suis surtout intéressé par les attaques contre MsSQL 2005 et 2008, car ils sont mes bases de données primaires, mais toutes les bases de données sont intéressantes.

Edit: Pour clarifier ce que je veux dire par des paramètres et des requêtes paramétrées. À l'aide de paramètres je veux dire en utilisant des "variables" au lieu de construire la requête sql dans une chaîne de caractères.
Donc au lieu de faire ceci:

SELECT * FROM Table WHERE Name = 'a name'

Nous faisons cela:

SELECT * FROM Table WHERE Name = @Name

et puis définissez la valeur de l' @Nom du paramètre de la requête / commande de l'objet.

50voto

Adam Bellaire Points 42797

Les espaces réservés sont assez pour éviter les injections. Vous pourriez toujours être ouvert à des dépassements de tampon, mais c'est une toute autre saveur de l'attaque à partir d'une injection SQL (le vecteur d'attaque ne serait pas de la syntaxe SQL, mais en binaire). Depuis les paramètres passés seront tous échappé correctement, il n'y a aucun moyen pour l'attaquant de passer des données qui seront traitées comme des "live" de SQL.

Vous ne pouvez pas utiliser les fonctions à l'intérieur des espaces réservés, et vous ne pouvez pas utiliser des espaces réservés comme de colonne ou de table des noms, parce qu'ils sont échappées et en a cité que les littéraux de chaîne.

Toutefois, si vous utilisez les paramètres dans le cadre d'une concaténation de chaîne à l'intérieur de votre requête dynamique, vous êtes toujours vulnérable à l'injection, car vos chaînes ne seront pas échappé, mais ce sera littérale. L'utilisation d'autres types de paramètres (nombre entier) est sûr.

Cela dit, si vous utilisez utilisez l'entrée pour définir la valeur de quelque chose comme security_level, alors quelqu'un pourrait juste faire eux-mêmes les administrateurs de votre système et avoir un libre-pour-tous. Mais c'est juste de base de la validation de l'entrée, et n'a rien à voir avec l'injection SQL.

13voto

Bill Karwin Points 204877

Non, il y a toujours des risques d'injection SQL tout moment vous interpoler non validées des données dans une requête SQL.

Les paramètres de la requête de l'aide afin d'éviter ce risque en séparant les valeurs littérales de la syntaxe SQL.

'SELECT * FROM mytable WHERE colname = ?'

C'est très bien, mais il y a d'autres fins de l'interpolation des données dans une dynamique de requête SQL qui ne peuvent pas utiliser les paramètres de la requête, parce que ce n'est pas une valeur SQL, mais au lieu d'un nom de table, la colonne nom, une expression, ou une autre syntaxe.

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

Il n'a pas d'importance si vous êtes à l'aide de procédures stockées ou de l'exécution de requêtes SQL directement depuis le code de l'application. Le risque est toujours là.

La solution dans ces cas est d'utiliser FIEO tant que de besoin:

  • Filtre d'Entrée: valider que les données légitimes entiers, les noms de table, les noms de colonnes, etc. avant de vous interpoler.

  • S'échapper de Sortie: dans ce cas de "sortie" signifie mettre des données dans une requête SQL. Nous utilisons des fonctions de transformer les variables utilisées comme des littéraux de chaîne dans une expression SQL, de sorte que les guillemets et autres caractères spéciaux à l'intérieur de la chaîne sont échappés. Nous devons aussi utiliser des fonctions pour transformer les variables qui pourraient être utilisés comme noms de table, les noms de colonnes, etc. Comme pour les autres éléments de la syntaxe, comme l'écrit l'ensemble des expressions SQL de manière dynamique, c'est un problème plus complexe.

12voto

mikekidder Points 679

Rune -

Voici un article daté, mais toujours valable:

Injection SQL - Les requêtes paramétrées sont-elles sécurisées?

12voto

RoadWarrior Points 11588

Il semble y avoir une certaine confusion dans ce fil de discussion au sujet de la définition de "paramétrer la requête".

  • SQL comme une procédure stockée qui accepte des paramètres.
  • SQL qui est appelé à l'aide le SGBD collection de Paramètres.

Compte tenu de l'ancienne définition, de nombreux liens montrent de travail attaques.

Mais la "normale" définition est la dernière. Compte tenu de cette définition, je ne sais pas du tout une attaque par injection SQL qui fonctionne. Cela ne veut pas dire qu'il n'y a pas une, mais j'ai pas encore le voir.

D'après les commentaires, je ne suis pas m'exprimer assez clairement, voici donc un exemple qui, nous l'espérons être plus clair:

Cette approche est ouverte à l'injection SQL

exec dbo.MyStoredProc 'DodgyText'

Cette approche n'est pas ouvert à l'injection SQL

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

10voto

Steven A. Lowe Points 40596

sql paramètre de type chaîne de caractères (varchar, nvarchar, etc) qui est utilisé pour construire une dynamique de requête est toujours vulnérable

sinon, le paramètre de conversion de type (par exemple, int, décimal, la date, etc.) devrait éliminer toute tentative d'injecter du sql par le biais du paramètre

EDIT: un exemple, où le paramètre @p1 est destiné à être un nom de table

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

Si @p1 est sélectionné à partir d'une liste déroulante, c'est un potentiel d'attaque par injection sql vecteur;

Si @p1 est formulé par programmation w/la capacité de l'utilisateur à intervenir alors qu'il n'est pas un potentiel d'attaque par injection sql vecteur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X