Pour autant que je sache, vous ne pouvez pas utiliser de requêtes paramétrées pour exécuter des instructions DDL/spécifier des noms de table, du moins pas dans Oracle ou Sql Server. Si je devais avoir une fonction TruncateTable folle et pouvoir éviter l'injection SQL, alors ce que je ferais serait de créer une procédure stockée qui vérifie si l'entrée est une table qui peut être tronquée en toute sécurité.
-- Sql Server specific!
CREATE TABLE TruncableTables (TableName varchar(50))
Insert into TruncableTables values ('MyTable')
go
CREATE PROCEDURE MyTrunc @tableName varchar(50)
AS
BEGIN
declare @IsValidTable int
declare @SqlString nvarchar(50)
select @IsValidTable = Count(*) from TruncableTables where TableName = @tableName
if @IsValidTable > 0
begin
select @SqlString = 'truncate table ' + @tableName
EXECUTE sp_executesql @SqlString
end
END
Le conseil le plus courant pour lutter contre l'injection SQL est d'utiliser les paramètres de requête SQL (plusieurs personnes sur ce fil ont suggéré de le faire).
Ce n'est pas la bonne réponse dans ce cas. Vous ne pouvez pas utiliser de paramètres de requête SQL sur les noms de table dans les instructions DDL.
Les paramètres de requête SQL ne peuvent être utilisés qu'à la place des valeurs littérales dans les expressions SQL. C'est la norme pour chaque implémentation SQL.
Lorsque vous avez des noms de table, ma recommandation pour empêcher l'injection SQL est de valider la chaîne d'entrée par rapport à une liste de noms de table connus.
Vous pouvez obtenir une liste de noms de tables valides à partir du INFORMATION_SCHEMA :
SELECT table_name
FROM INFORMATION_SCHEMA.Tables
WHERE table_type = 'BASE TABLE'
AND table_name = @tableName
Vous pouvez désormais transmettre des variables d'entrée en tant que paramètres SQL à cette requête. Si la requête ne renvoie aucune ligne, vous savez que l'entrée n'est pas valide et ne peut pas être utilisée comme table. Si la requête renvoie une ligne, elle correspond, vous pouvez donc l'utiliser avec plus de confiance.
Vous pouvez également valider les noms de tables par rapport à une liste spécifique de tables que vous définissez comme disponibles pour que l'application les tronque, comme @John Buchanan suggéré.
Même après avoir vérifié que tableName existe en tant que nom de table dans votre SGBDR, je suggérerais également de délimiter le nom de la table, juste au cas où vous utiliseriez des noms de table avec des espaces ou des caractères spéciaux. Dans Microsoft SQL Server, les délimiteurs d'identifiant par défaut sont des crochets :
Maintenant, vous ne risquez une injection SQL que si tableName correspond à une vraie table et que vous utilisez réellement des crochets dans les noms de vos tables !
Pour autant que je sache, vous ne pouvez pas utiliser de requêtes paramétrées pour exécuter des instructions DDL/spécifier des noms de table, du moins pas dans Oracle ou Sql Server. Si je devais avoir une fonction TruncateTable folle et pouvoir éviter l'injection SQL, alors ce que je ferais serait de créer une procédure stockée qui vérifie si l'entrée est une table qui peut être tronquée en toute sécurité.
Le conseil le plus courant pour lutter contre l'injection SQL est d'utiliser les paramètres de requête SQL (plusieurs personnes sur ce fil ont suggéré de le faire).
Ce n'est pas la bonne réponse dans ce cas. Vous ne pouvez pas utiliser de paramètres de requête SQL sur les noms de table dans les instructions DDL.
Les paramètres de requête SQL ne peuvent être utilisés qu'à la place des valeurs littérales dans les expressions SQL. C'est la norme pour chaque implémentation SQL.
Lorsque vous avez des noms de table, ma recommandation pour empêcher l'injection SQL est de valider la chaîne d'entrée par rapport à une liste de noms de table connus.
Vous pouvez obtenir une liste de noms de tables valides à partir du
INFORMATION_SCHEMA
:Vous pouvez désormais transmettre des variables d'entrée en tant que paramètres SQL à cette requête. Si la requête ne renvoie aucune ligne, vous savez que l'entrée n'est pas valide et ne peut pas être utilisée comme table. Si la requête renvoie une ligne, elle correspond, vous pouvez donc l'utiliser avec plus de confiance.
Vous pouvez également valider les noms de tables par rapport à une liste spécifique de tables que vous définissez comme disponibles pour que l'application les tronque, comme @John Buchanan suggéré.
Même après avoir vérifié que
tableName
existe en tant que nom de table dans votre SGBDR, je suggérerais également de délimiter le nom de la table, juste au cas où vous utiliseriez des noms de table avec des espaces ou des caractères spéciaux. Dans Microsoft SQL Server, les délimiteurs d'identifiant par défaut sont des crochets :Maintenant, vous ne risquez une injection SQL que si
tableName
correspond à une vraie table et que vous utilisez réellement des crochets dans les noms de vos tables !