I have a dynamic script running on all of the objects in a database and change the schema name for every one from [dbo] to the database name.
The script is working just fine, I would like to know if I can do anything better in order to secure it from SQL Injection?
BEGIN TRANSACTION
/* Change schema to all objects in database (from dbo)*/
DECLARE @SchemaName SYSNAME = db_name();
DECLARE @SQL NVARCHAR(MAX) = N'IF Not Exists (select 1 from sys.schemas where schema_id = SCHEMA_ID(@NewSchemaName))
EXEC(''CREATE SCHEMA ''+@NewSchemaName+'''')' + NCHAR(13) + NCHAR(10);
SELECT @SQL = @SQL + N'EXEC(''ALTER SCHEMA ''+@NewSchemaName+'' TRANSFER [' + SysSchemas.Name + '].[' + DbObjects.Name + ']'');' + NCHAR(13) + NCHAR(10)
FROM sys.Objects DbObjects
INNER JOIN sys.Schemas SysSchemas
ON DbObjects.schema_id = SysSchemas.schema_id
WHERE SysSchemas.Name = 'dbo'
AND (DbObjects.Type IN ('U', 'P', 'V'))
EXECUTE sp_executesql @sql, N'@NewSchemaName sysname', @NewSchemaName = @SchemaName
ROLLBACK
In my quest of securing this one, I used this great article by Thom Andrews: Dos and Don'ts of Dynamic SQL
this is where I started: github.com/NathanLifshes
QUOTENAME. Rather than'...[' + SysSchemas.Name + ']...'you want'...' + QUOTENAME(SysSchemas.Name) + '...'. For yourALTER SCHEMAstatement, you'll also inject@NewSchemaNameas well (usingQUOTENAME), asALTERcan't accept a variable as an input, it's needs a literal.]character in them, and if you did they would need to be escaped properly. Your'['and']'that wrap it would cover any things like white space, but it's best to ensure that nothing can slip through.EXECcommand" Why are you creating dynamic SQL inside your dynamic SQL?