Prévenir les injections SQL en C# avec Entity Framework
30 juillet 2024
0 minutes de lectureL’importance de prévenir les injections SQL
L’injection SQL (SQLi) est l’une des vulnérabilités de sécurité les plus graves des applications web. Elle se produit lorsqu’un attaquant parvient à manipuler les requêtes SQL exécutées par une application en injectant du code SQL malveillant dans les champs de saisie utilisateur. Une attaque SQLi peut permettre d’accéder sans autorisation à des données sensibles, de corrompre des données, voire de prendre le contrôle total du serveur de base de données. Prévenir les attaques SQLi est essentiel pour préserver l’intégrité, la confidentialité et la disponibilité des données, ainsi que la sécurité globale de l’application.
L’une des erreurs les plus courantes consiste à construire des requêtes SQL par concaténation de chaînes. Avec cette approche, les paramètres fournis par l’utilisateur font partie de la requête SQL et peuvent influer sur son exécution. Voici un exemple de code C# vulnérable :
En utilisant des caractères tels que ; et --, nous pouvons influer sur l’exécution de la requête en y mettant fin plus tôt que prévu (;) et en traitant le reste de la chaîne comme un commentaire (--).
Si le nom est défini sur Brian'; DROP TABLE Users;-- , la requête devient :
La requête initiale s’arrête après ;. Une nouvelle requête supprimant la table Users est alors exécutée, et le reste de la requête d’origine est considéré comme un commentaire. De la même manière, il est possible de modifier ou d’insérer des données dans la base de données si les requêtes SQL sont implémentées ainsi.
Échappement ou requêtes préparées
L’essentiel est de séparer les paramètres d’entrée de la requête proprement dite afin que les données saisies par l’utilisateur ne puissent plus influer sur son exécution. De nombreux langages proposent des fonctions permettant d’utiliser des requêtes paramétrées et de séparer ainsi les données utilisateur de la requête proprement dite.
Reste à savoir comment cela fonctionne en coulisses : il existe essentiellement deux méthodes pour y parvenir, l’échappement ou l’utilisation de requêtes préparées.
Échappement
L’échappement consiste à assainir les données saisies par l’utilisateur en ajoutant des caractères d’échappement devant les caractères potentiellement dangereux, comme les guillemets. Toutefois, cette méthode est sujette aux erreurs et n’est pas infaillible. L’échappement est effectué côté client (dans l’application), puis la requête échappée est envoyée à la base de données sous la forme d’une instruction unique. Cette méthode exige une gestion minutieuse de nombreux cas particuliers et n’est généralement pas recommandée comme protection principale contre les attaques SQLi.
Requêtes préparées
Les requêtes préparées, qui utilisent des requêtes SQL paramétrées, fonctionnent différemment. La structure SQL est définie séparément et envoyée au serveur de base de données lors d’une première étape. La base de données peut alors créer le plan d’exécution avant même que les paramètres n’entrent en jeu. Lors d’une seconde étape, les paramètres sont envoyés à la base de données. Le plan d’exécution ayant déjà été créé, les paramètres sont toujours traités comme des données, et non comme du code exécutable, et ne peuvent pas influer sur l’exécution.
Prévenir les injections SQL avec Entity Framework
Entity Framework (EF) propose plusieurs méthodes pour interagir avec la base de données en toute sécurité, sans exposer l’application aux vulnérabilités SQLi. Elles comprennent les requêtes LINQ, FromSqlInterpolated et FromSqlRaw avec des paramètres explicites.
Utiliser LINQ
Language Integrated Query (LINQ) offre une méthode sécurisée pour interagir avec les bases de données. C’est la méthode recommandée pour interroger une base de données avec EF dans la plupart des cas. LINQ fournit un haut niveau d’abstraction : vous pouvez écrire directement des requêtes en C# sans connaître la syntaxe SQL. LINQ étant intégré à C#, vous bénéficiez de la vérification de la syntaxe à la compilation.
Entity Framework convertit automatiquement les requêtes LINQ en SQL à l’aide de requêtes préparées et de paramètres, ce qui empêche les injections SQL.
Bien que LINQ soit pratique et sécurisé, il peut parfois générer du SQL moins efficace que des requêtes SQL écrites à la main, notamment pour les requêtes complexes. La couche de traduction peut entraîner une surcharge de performances. De plus, les possibilités de LINQ dépendent de la capacité du fournisseur EF à traduire le code C# en SQL. Certaines fonctionnalités SQL complexes, comme certains types de jointures, de sous-requêtes ou de fonctions de fenêtrage, peuvent être difficiles, voire impossibles, à exprimer avec LINQ.
Utiliser FromSqlInterpolated
FromSqlInterpolated est une autre méthode sécurisée pour exécuter des requêtes SQL brutes. Elle utilise l’interpolation de chaînes et gère automatiquement le paramétrage, en s’appuyant également sur des requêtes préparées.
Avec FromSqlInterpolated, EF garantit que la variable name est correctement paramétrée, ce qui protège contre les injections SQL. Entity Framework Core analyse la chaîne interpolée et identifie les expressions interpolées. Il remplace ensuite ces expressions par des espaces réservés pour les paramètres dans la commande SQL. Les paramètres SQL correspondants sont créés, et les valeurs des expressions interpolées leur sont attribuées.
En coulisses, la fonction FromSqlInterpolated utilise une requête préparée avec des paramètres. Elle protège donc contre les injections SQL. Lorsque vous devez effectuer des requêtes plus complexes, plus faciles à exprimer en SQL qu’avec la syntaxe LINQ, FromSqlInterpolated est une excellente solution.
Utiliser FromSqlRaw avec des paramètres explicites
Dans l’exemple initial, nous avons d’abord créé la requête, puis l’avons transmise dans son intégralité à l’instruction FromSQLRaw. Pourtant, FromSqlRaw peut être utilisé en toute sécurité. En utilisant des paramètres explicites avec FromSqlRaw, EF garantit que les données utilisateur sont correctement paramétrées, ce qui prévient les injections SQL. Cette méthode consiste à définir des requêtes SQL avec des espaces réservés pour les paramètres et à fournir les valeurs séparément, afin que les données utilisateur soient traitées comme des données et non comme du code exécutable.
Dans cette version, l’espace réservé {0} est utilisé dans la chaîne de requête SQL, et la valeur du paramètre est transmise directement comme argument à FromSqlRaw. Les données utilisateur sont ainsi correctement paramétrées, ce qui protège contre les injections SQL.
Détecter, corriger et prévenir
La différence entre une utilisation sûre ou non de FromSqlRaw est minime et facile à manquer. C’est pourquoi chaque développeur devrait utiliser des outils comme Snyk Code pour signaler les constructions de code non sécurisées en C#.

Dans l’exemple ci-dessus, un problème similaire d’injection SQL est détecté grâce à l’intégration Git. Vérifier la présence de ce type de problèmes tout au long du cycle de développement est essentiel si la sécurité vous tient à cœur, sans pour autant sacrifier la rapidité.
Toutefois, il est également essentiel de bien connaître les frameworks utilisés et de se former à leur utilisation. Avec EF, privilégiez par défaut la syntaxe LINQ. Elle devrait suffire, sauf si vous avez besoin de performances élevées ou devez créer des requêtes très complexes. Pour des requêtes SQL très spécifiques et complexes, utilisez l’approche FromSqlInterpolated décrite ci-dessus. Je vous conseille d’éviter FromSqlRaw. Même si cette méthode peut être utilisée en toute sécurité, la différence entre une bonne et une mauvaise approche est subtile et facile à manquer.
Pour résumer, voici une liste facile à retenir. Avec Entity Framework :
Utilisez la syntaxe LINQ pour interagir avec la base de données et éviter le SQL.
Réservez FromSQLInterpolated aux cas complexes.
Utilisez un outil d’analyse de code comme Snyk Code pour vous aider à détecter les erreurs.
Maintenant que vous en savez un peu plus, vous êtes prêt à utiliser Entity Framework en C# pour protéger votre code contre les vulnérabilités d’injection SQL. Pour vous faciliter la tâche, créez un compte Snyk gratuit ou réservez une démo dès aujourd’hui pour découvrir comment Snyk sécurise votre code au fil de son écriture.
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.


