flawopen.com/Injection SQL/Procédures stockées
Les procédures stockées empêchent-elles l’injection SQL ?
Non — c’est une idée reçue fréquente. Une procédure stockée ne protège que si elle lie ses paramètres en interne. Si elle concatène ses entrées dans une chaîne SQL exécutée avec EXEC ou sp_executesql, elle est aussi vulnérable qu’une concaténation dans l’application.
-- SQL Server T-SQL; dbo.Users.Id is NVARCHAR(50).
CREATE PROCEDURE dbo.GetUser
@UserId NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(MAX) =
N'SELECT Id FROM dbo.Users WHERE Id = N'''
+ @UserId + N'''';
EXEC(@sql);
END;
-- SQL Server T-SQL; same illustrative schema.
CREATE PROCEDURE dbo.GetUser
@UserId NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(MAX) =
N'SELECT Id FROM dbo.Users WHERE Id = @id';
EXEC sys.sp_executesql
@stmt = @sql,
@params = N'@id NVARCHAR(50)',
@id = @UserId;
END;
Pourquoi cette idée reçue est courante
« Utilisez des procédures stockées » est souvent présenté comme une solution générale contre l’injection SQL. C’est vrai si la procédure transmet les valeurs comme paramètres liés dans une requête normale. Si elle construit du SQL dynamique avec EXEC et concatène des valeurs non fiables, elle réintroduit le même risque. Si le SQL dynamique est nécessaire, liez les valeurs avec sp_executesql. Les noms de tables ou colonnes ne sont pas des valeurs liables ; mappez les choix autorisés à des identifiants fixes via une liste d’autorisation.
Questions fréquentes
Oui. sp_executesql accepte des paramètres : déclarez-les et transmettez les valeurs séparément (par exemple EXEC sp_executesql @sql, N'@id INT', @id = @UserId). Ne concaténez pas de valeurs dans @sql. Pour les noms dynamiques de table ou de colonne, utilisez une liste d’autorisation stricte, car les identifiants ne sont pas des paramètres liables.