flawopen.com/SQL Injection en C#/EF Core FromSqlRaw
FromSqlRaw d’Entity Framework Core est-il sûr ?
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.
// 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);
// 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.
- ✓Pour les valeurs, utilisez FromSqlInterpolated/FromSql avec une interpolation directe, ou FromSqlRaw avec des paramètres séparés.
- ✓Ne transmettez jamais de données utilisateur concaténées ou interpolées à FromSqlRaw. Ne convertissez pas d’abord un FormattableString en string.
- ✓Pour les identifiants dynamiques, choisissez dans une liste autorisée fixe. Vérifiez séparément les droits et l’indexation du champ.
- ✓Préférez LINQ si elle exprime clairement la requête ; le paramétrage bloque l’injection de syntaxe SQL, mais n’applique ni autorisations ni règles métier.
Comment vérifier votre code
rg -n -g '*.cs' '(FromSqlRaw|FromSqlInterpolated|FromSql)\s*\(' .Questions fréquentes
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.
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.
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
- Microsoft Learn — requêtes SQL et paramètres EF Core
- Microsoft Learn — API FromSqlRaw
- Microsoft Learn — API FromSqlInterpolated
- OWASP — prévention des injections SQL
- FlawOpen — SQL Injection en C#