FlawOpen

flawopen.com/SQL Injection en C#/EF Core FromSqlRaw

FromSqlRaw d’Entity Framework Core est-il sûr ?

Guide de référence
Réponse courte

Oui, si les valeurs restent séparées du texte SQL. FromSqlRaw accepte du SQL brut : concaténer ou interpoler une entrée non fiable dans sa chaîne peut modifier la requête. Utilisez des arguments de paramètres séparés ou transmettez un FormattableString interpolé à FromSqlInterpolated (ou à FromSql avec EF Core 7+). Un paramètre est comme un compartiment scellé : la base reçoit la valeur, pas de nouvelles instructions SQL.

DANGEREUX — l’interpolation devient une chaîne ordinaire
// L’interpolation est d’abord évaluée en chaîne.
var sql = $"SELECT * FROM Users WHERE Id = {id}";

// FromSqlRaw reçoit du texte SQL, pas un FormattableString.
var query = context.Users.FromSqlRaw(sql);
SÛR — les valeurs restent des paramètres
// EF Core 3–6 : marqueur positionnel et valeur séparée.
var byRawParameter = context.Users.FromSqlRaw(
    "SELECT * FROM Users WHERE Id = {0}", id);

// EF Core 3+ : transmettez l’interpolation à l’API paramétrée.
var byInterpolation = context.Users.FromSqlInterpolated(
    $"SELECT * FROM Users WHERE Id = {id}");

// EF Core 7+ : FromSql accepte aussi FormattableString.
var byFromSql = context.Users.FromSql(
    $"SELECT * FROM Users WHERE Id = {id}");

Le point contre-intuitif

FromSqlInterpolated reçoit un FormattableString. EF Core lit son format et ses arguments, puis envoie chaque valeur interpolée comme paramètre distinct à la base ; aucune interception à la compilation n’intervient. EF Core 7 a ajouté FromSql avec le même comportement sûr pour les chaînes interpolées. Les versions antérieures utilisent FromSqlInterpolated. FromSqlRaw est également sûr si des marqueurs comme {0} correspondent aux valeurs passées séparément. Une chaîne interpolée stockée d’abord dans un string a déjà perdu ses métadonnées de paramètres.

Les paramètres lient des valeurs, pas des noms de colonnes

Un paramètre représente une valeur, pas un nom de table ou de colonne, un opérateur SQL ni un sens de tri. Si la structure de la requête doit varier, choisissez chaque identifiant dans une liste autorisée fixe du code applicatif ; ne tentez pas de paramétrer les identifiants et ne remplacez pas la liste par un filtrage de caractères. Vérifiez aussi les autorisations et le coût : une colonne valide peut exposer des données sensibles ou déclencher des analyses coûteuses.

Comment vérifier votre code

rg -n -g '*.cs' '(FromSqlRaw|FromSqlInterpolated|FromSql)\s*\(' .
Pour chaque appel, vérifiez la surcharge et le type d’argument. Suivez les données non fiables pour repérer une concaténation, une interpolation passée à FromSqlRaw ou un FormattableString converti en string ; examinez séparément les identifiants dynamiques.

Questions fréquentes

FromSqlRaw est-il sûr avec des paramètres ?

Oui, si le SQL contient des marqueurs et si les valeurs sont transmises comme arguments séparés, par exemple FromSqlRaw("... {0}", value). Ne concaténez pas et n’interpolez pas la valeur dans la chaîne SQL au préalable.

Pourquoi FromSqlInterpolated est-il sûr avec une chaîne interpolée C# ?

Il reçoit un FormattableString, qui sépare le format des valeurs. EF Core transforme chaque valeur en paramètre de base. Si vous affectez d’abord l’interpolation à un string ou la transmettez à FromSqlRaw, cette protection disparaît.

Les paramètres peuvent-ils remplacer des noms de table ou de colonne ?

Non. Les paramètres représentent uniquement des valeurs. Pour les identifiants dynamiques, associez les choix utilisateur à une liste fixe d’identifiants connus et vérifiez les autorisations et le coût de la requête.

Références

À voir aussi Injection SQL (CWE-89) : fonctionnement et prévention dans chaque langage — flawopen.com FastAPI et SQL Injection : limites de Pydantic GORM Raw SQL : éviter l’injection SQL en Go Échapper les guillemets suffit-il contre SQL Injection ? Utiliser un ORM suffit-il à prévenir l'injection SQL ? Knex.js protège-t-il contre les injections SQL ? MyBatis ${} et #{} : prévenir la SQL Injection