SQL Server har så många saker att lära sig och jag tycker alltid att den är fantastisk. Mina samtal med kunder kommer ofta med säkerhetsfrågor, speciellt kring SQL Injection. Många har hävdat att SQL Injection är ett SQL Server-problem. Det tar ganska lång tid för mig att låta dem veta att det inte finns något om SQL Server och SQL Injection. SQL-injektion är ett resultat av felaktig kodning. En av rekommendationerna jag ger handlar om att inte använda Dynamic SQL. Det kan finnas vissa situationer där du inte kan undvika det. Mitt enda råd är att undvika om möjligt. I den här bloggen skulle jag visa ett SQL Injection-problem på grund av dynamisk SQL och en möjlig lösning du kan ha.
Låt oss anta att vi har en enkel söksida där användaren kan använda den tomma sökningen eller tillhandahålla filter i vilket fält som helst. Vi har tillhandahållit två fält för att använda "Förnamn" och "Efternamn". Användaren skriver något och trycker på sök. Här är vår kod för lagrad procedur som skjuter bakom platsen.
USE AdventureWorks2014 GO CREATE PROCEDURE search_first_or_last @firstName NVARCHAR(50) ,@lastName NVARCHAR(50) AS BEGIN DECLARE @sql NVARCHAR(4000) SELECT @sql = ' SELECT FirstName ,MiddleName, LastName' + ' FROM Person.Person WHERE 1 = 1 ' IF @firstName IS NOT NULL SELECT @sql = @sql + ' AND FirstName LIKE ''' + @firstName + '''' IF @lastName IS NOT NULL SELECT @sql = @sql + ' AND LastName LIKE ''' + @lastName + '''' EXEC (@sql) END
Om jag använder den här strängen för att köra i efternamn "; släpp tabell t1–
EXEC search_first_or_last '%K%', ''';drop table t1--'
Den dynamiska strängen skulle vara
SELECT FirstName, MiddleName, LastName FROM Person. Person WHERE 1 = 1 AND FirstName LIKE '%K%' AND LastName LIKE '';DROP TABLE t1--'
Ser du problemet? Ja, användare kan släppa tabell t1 om koden körs under ett konto med hög behörighet.
En av lösningarna på problemet skulle vara att använda sp_executesql. Här är den bättre versionen som använder
CREATE PROCEDURE search_first_or_last @firstName NVARCHAR(50) ,@lastName NVARCHAR(50) AS BEGIN DECLARE @sql NVARCHAR(4000) SELECT @sql = ' SELECT FirstName , MiddleName, LastName' + ' FROM Person.Person WHERE 1 = 1 ' IF @firstName IS NOT NULL SELECT @sql = @sql + ' AND FirstName LIKE @firstName' IF @lastName IS NOT NULL SELECT @sql = @sql + ' AND LastName LIKE @lastName ' EXEC sp_executesql @sql ,N'@firstName nvarchar(50), @lastName nvarchar(50)' ,@firstName ,@lastName END
Hoppas du skulle kunna använda detta och implementera i ditt projekt. Använder du dessa enkla tekniker i din produktionskod? Har du någonsin stött på liknande problem under revisionen? Låt mig veta om dina lärdomar.