SQL Server ma tak wiele do nauczenia się i zawsze uważam to za niesamowite. W moich rozmowach z klientami często pojawiają się pytania dotyczące bezpieczeństwa, zwłaszcza dotyczące SQL Injection. Wielu twierdziło, że wstrzyknięcie SQL jest problemem SQL Server. Zajęło mi trochę czasu, zanim dowiedziałem się, że nie ma nic o SQL Server i SQL Injection. SQL Injection jest wynikiem złych praktyk kodowania. Jedno z moich zaleceń dotyczy nieużywania Dynamic SQL. Mogą wystąpić sytuacje, w których nie można tego uniknąć. Moją jedyną radą byłoby unikanie, jeśli to możliwe. W tym blogu zademonstrowałbym problem wstrzykiwania SQL z powodu dynamicznego SQL i możliwego rozwiązania.
Załóżmy, że mamy prostą stronę wyszukiwania, na której użytkownik może użyć pustego wyszukiwania lub wprowadzić filtr w dowolnym polu. Udostępniliśmy dwa pola do użycia „Imię” i „Nazwisko”. Użytkownik coś wpisuje i klika w wyszukiwarkę. Oto nasz kod procedury składowanej, która uruchamia się za kulisami.
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
Jeśli użyję tego ciągu do wykonania na nazwisko ”;upuść tabelę t1–
EXEC search_first_or_last '%K%', ''';drop table t1--'
ciąg dynamiczny byłby
SELECT FirstName, MiddleName, LastName FROM Person. Person WHERE 1 = 1 AND FirstName LIKE '%K%' AND LastName LIKE '';DROP TABLE t1--'
Czy widzisz problem? Tak, użytkownicy mogą usunąć tabelę t1, jeśli kod działa na koncie o wysokim poziomie uprawnień.
Jednym z rozwiązań problemu byłoby użycie sp_executesql. Oto lepsza wersja za pomocą
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
Mam nadzieję, że będziesz w stanie to wykorzystać i wdrożyć w swoim projekcie. Czy używasz tych prostych technik w swoim kodzie produkcyjnym? Czy kiedykolwiek napotkałeś podobne problemy podczas audytu? Daj mi znać o swoich odkryciach.