.Net, SQL Server, et les requêtes paramétrées (C#)Date de publication : 05/09/2004
Par
Ronald VASSEUR (autres articles) Utilisation des requêtes paramétrées avec SQL Server et C# Avant propos 1. Introduction 2. Les attaques de type injection SQL 3. Les requêtes paramétrées 4. Les classes du .Net framework 5. Les requêtes paramétrées dans le code 6. Les avantages et inconvénients 7. Conclusion Ressources Avant propos
Au cours de cet article nous allons étudier l'utilisation de requêtes paramétrées dans le cadre d'une application
ASP.Net codée en C#, il est évident que cela peut être étendu aux autres types d'applications et langages .Net
moyennant quelques petites adaptations mineures. Les requêtes paramétrées avec SqlParameter (ce qui est ici le cas)
fonctionnent avec SQL Server mais aussi avec MSDE
1. Introduction
Une vulnérabilité des applications ASP.Net utilisant une base de données est le fait que l'utilisateur puisse exécuter
des commandes SQL alors que théoriquement cela devrait lui être impossible. Ce type d'attaque peut potentiellement
permettre à un utilisateur de compromettre l'intégrité des données et de la base elle-même. Cette vulnérabilité est
connue sous le nom d'injection SQL. Ce problème de sécurité se pose, par exemple, lorsqu'un utilisateur rempli des
champs d'un formulaire dont le contenu sera concaténé directement à l'intérieur des requêtes envoyées à la base
de données.
2. Les attaques de type injection SQL
Pour vous montrer l'intérêt d'employer des requêtes SQL paramétrées, il est utile de voir à quel point la sécurité
des données peut être compromise si l'on n'applique pas quelques principes simples.
Prenons, pour cela, un exemple concret. Imaginons que votre application contienne un formulaire permettant de faire une recherche dans votre base de données en retournant les enregistrements correspondants à des critères établis par l'utilisateur. De plus, admettons qu'un champ permette à l'utilisateur d'entrer un texte au clavier pour déclarer à l'application ce qu'il recherche. L'utilisateur normal va taper les mots clés en relation avec ce qu'il recherche, mais là où il y a danger, c'est qu'un utilisateur malveillant va non pas taper de simples mots clés mais des instructions SQL dans le but de modifier ou détruire vos données. En effet, sans l'emploi de requêtes paramétrées, il y a de grandes chances que le code de la requête dans votre application soit :
Pour l'utilisateur malveillant souhaitant effacer des données c'est alors un jeu d'enfant
Dans le champ de
votre formulaire il va par exemple saisir des commandes SQL, ou encore employer des apostrophes, ou même des
points virgules permettant ainsi d'ajouter de nouvelles instructions à la première requête transmise par
l'application. Voici concrètement à quoi va ressembler dans le code une telle attaque :
L'utilisateur malveillant va alors saisir dans maTextBox :
La requête complète, dans votre application, va alors être :
Cela va avoir pour conséquence directe d'effacer tous les enregistrements de votre table
Cela bien entendu
si le compte utilisé pour la requête n'est pas autorisé à faire seulement des SELECT sur la table concernée,
cela est malheureusement très souvent le cas pour des raisons de commodité et de " qui peut le plus peut le moins
"
ainsi l'on se débarrasse vite fait d'une gestion fine et efficace des droits ; en utilisant tout le temps le
compte SA pour faire de simples SELECT
Bien entendu, cela suppose également que l'utilisateur malveillant connaisse un minimum la structure de votre base de données, mais il ne faut absolument pas sous estimer ce risque, surtout que tout le monde a toujours tendance à avoir des structures similaires. J'ai pris un exemple volontairement simpliste, mais il est clair que vu la richesse des différentes versions du langage SQL employées avec les bases de données actuelles les attaques peuvent être beaucoup plus subtiles. Vous comprenez, désormais, à quel point votre application peut être en danger face une attaque de type SQL Injection. Il faut donc proscrire la concaténation de chaînes dans les requêtes SQL de vos applications ASP.Net et n'employer que des requêtes paramétrées ou des procédures stockées. 3. Les requêtes paramétrées
Une requête paramétrée est, en fait, une commande SQL comme les autres sauf que l'on lui passe une collection de
paramètres dont le type et la taille ont été définis. Les paramètres dans la requête sont nommés avec un @ comme
premier caractère.
Il faut aussi, préalablement à l'exécution de la requête, définir la taille et le type des paramètres, mais nous
verrons cela un peu plus tard.
4. Les classes du .Net framework
Les classes qui sont concernées sont les suivantes : SqlParameter est la classe qui permet de gérer ces paramètres, sa méthode la plus utilisée est Add, en effet c'est elle qui permet d'ajouter les paramètres à nôtre requête. Entre en jeu aussi les classes SqlCommand, SqlConnection qui permettent de définir des commandes T-SQL et de se connecter à SQL Server, plus largement les classes concernées sont celles de l'espace de noms System.Data.SqlClient. Cet espace de noms est le fournisseur de données .Net pour Microsoft SQL Server®. Remarque : pour utiliser toutes ces fonctionnalités il faut importer l'espace de noms cité précédemment en ajoutant la ligne de code Imports System.Data.SqlClient, cet espace contient la classe SqlParameter qui nous intéresse ici. 5. Les requêtes paramétrées dans le code
L'exemple, ci-dessous, vous montre ce qu'est une requête paramétrée, elle permet d'insérer des données dans
une base de données
Maintenant, il ne suffit pas d'avoir ce code et de le copier, il faut surtout le comprendre. Il n'est pas nécessaire
d'expliquer les premières lignes en effet elles sont exactement les mêmes que pour une requête non paramétrée.
Là où cela diffère c'est lorsque l'on déclare les paramètres.
Les paramètres sont, en fait, ajoutés à myCommand qui est un objet sqlCommand, c'est-à-dire une chaîne d'instructions en Transact-SQL qui doit être exécutée par SQL Server. Pour ajouter un paramètre à un objet sqlCommand, rien de plus simple, il suffit d'ajouter le code suivant :
Si notre paramètre se nomme param1 et qu'il est de type Integer voilà ce que va donner notre ligne :
Les paramètres peuvent êtres de types différents, voilà une liste exhaustive des types existants :
Après avoir déterminé le nom et le type, il faut déterminer la taille. Pour les chaînes, la taille détermine le nombre de
caractères, sinon elle détermine sa taille en octets. Comme nous pouvons le voir ci-dessous, notre chaîne VarChar pourra
avoir une longueur maximale de 25 caractères.
Ou encore ici notre entier sera codé sur 4 octets.
Maintenant que nous avons typé et dimensionné le paramètre, il faut lui attribuer une valeur, ici nous récupérons
le texte contenu dans maTextBox1.
Nous voyons que pour @id_article et @prix_article, il a fallu réaliser un cast sur ce que nous avons récupéré,
en effet, nous récupérons deux chaînes de caractères que nous voulons transformer respectivement en données de
type entier et double. Ce qui explique l'emploi de Convert.ToInt32 et Convert.ToDouble .
Et enfin, la dernière étape est tout simplement l'exécution de la requête précédée de l'ouverture de la connexion avec le serveur de base de données et suivie de sa fermeture.
6. Les avantages et inconvénients
Les avantages :
Les inconvénients :
Même si le fait d'employer des requêtes paramétrées est un atout très important au niveau de la sécurité, il ne faut
pourtant pas croire que cela est suffisant. Il est indispensable de configurer correctement sa base de données,
avec des comptes ayant des accès en adéquation avec leurs besoins, par exemple ne pas utiliser le compte SA pour
faire un SELECT sur une table (par ailleurs, il ne faut jamais utiliser le compte SA dans une application, sauf
nécessité absolue).
De plus, même si nos paramètres sont typés, cela ne signifie pas qu'il y a un contrôle du type avant l'exécution de la requête, en clair si dans un champ devant contenir un entier, un utilisateur saisit 12,43, il va alors y avoir un plantage pur et simple. Il faut donc avoir une gestion des erreurs qui soit efficace avec pourquoi pas, une vérification côté client (si le navigateur le permet) et côté serveur des données. La validation de formulaire étant très bien implémentée dans le Framework .Net, ces opérations ne sont pas difficiles à réaliser et apportent sécurité et fiabilité à votre application. Donc, pour résumer, il n'y a pas de réel inconvénient, le seul est que l'on pourrait croire que l'emploi de requêtes paramétrées est suffisant, mais attention cela n'est pas le cas. 7. Conclusion
L'emploi de requêtes paramétrées ne signifie bien évidemment pas qu'il n'est plus nécessaire de se préoccuper de la
sécurité au niveau de la base de données elle-même ! Elle est toujours aussi importante comme nous venons de le voir
juste précédemment. Mais cependant nous pouvons dire qu'au plan de la sécurité les requêtes paramétrées sont un atout
important. La concaténation de chaînes dans les requêtes SQL est à proscrire dès que cela vous est possible.
Ressources
Documentation relative à la classe SQLparameter : Cliquez ici
Documentation relative à l'espace de nom System.Data.SqlClient : Cliquez ici
Un grand merci à Freegreg, Morpheus et Bidou pour leur aide.
|
Copyright © 2004 Ronald VASSEUR. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Cette page est déposée.
Copyright © 2000-2013 - www.developpez.com