SQL Server има толкова много неща за научаване и винаги го намирам за невероятно. В разговорите ми с клиенти често се появяват въпроси за сигурност, особено около SQL инжектирането. Мнозина твърдят, че SQL инжектирането е проблем на SQL Server. Отнема доста време, за да ги уведомя, че няма нищо за SQL Server и SQL Injection. SQL инжекцията е резултат от грешни практики за кодиране. Една от препоръките, които давам, е да не използвате Dynamic SQL. Може да има някои ситуации, в които не можете да го избегнете. Единственият ми съвет би бил, избягвайте, ако е възможно. В този блог ще демонстрирам проблем с инжектирането на SQL поради динамичен SQL и възможно решение, което можете да имате.
Да предположим, че имаме проста страница за търсене, където потребителят може да използва празното търсене или да предостави филтър във всяко поле. Предоставихме две полета за използване на „Име“ и „Фамилия“. Потребителят въвежда нещо и натиска търсене. Ето нашия код на съхранена процедура, който се задейства зад сцената.
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
Ако използвам този низ за изпълнение на фамилно име ”;пуснете таблица t1–
EXEC search_first_or_last '%K%', ''';drop table t1--'
Динамичният низ ще бъде
SELECT FirstName, MiddleName, LastName FROM Person. Person WHERE 1 = 1 AND FirstName LIKE '%K%' AND LastName LIKE '';DROP TABLE t1--'
Виждате ли проблема? Да, потребителите могат да хвърлят таблица t1, ако кодът се изпълнява под акаунт с високи привилегии.
Едно от решенията на проблема би било използването на sp_executesql. Ето по-добрата версия с
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
Надявам се, че ще можете да използвате това и да приложите във вашия проект. Използвате ли тези прости техники във вашия производствен код? Сблъсквали ли сте се някога с подобни проблеми по време на одит? Уведомете ме за вашите знания.