Я сделал следующую хранимую процедуру:
ALTER PROCEDURE usp_actorBirthdays (@nameString nvarchar(100), @actorgender nvarchar(100))
AS
SELECT ActorDOB, ActorName FROM tblActor
WHERE ActorName LIKE '%' + @nameString + '%'
AND ActorGender = @actorgender
Теперь я попытался сделать что-то вроде этого. Может быть, я делаю это неправильно, но я хочу быть уверен, что такая процедура может предотвратить любую инъекцию SQL:
EXEC usp_actorBirthdays 'Tom', 'Male; DROP TABLE tblActor'
На рисунке ниже показано, что SQL выше выполняется в SSMS и результаты отображаются правильно, а не ошибка:
Кстати, я добавил эту часть после точки с запятой после выполнения запроса. Затем я выполнил это снова, но когда я проверил, существует ли таблица tblActor или нет, она все еще была там. Я делаю что-то неправильно? Или это действительно инъекционный? Я думаю, что я пытаюсь спросить здесь также, является ли хранимая процедура, как это безопасно? Спасибо.
EXEC usp_actorBirthdays 'Tom', 'Male''; DROP TABLE tblActor'
Ответы:
Этот код работает правильно, потому что это:
Чтобы SQL-инъекция работала, вы должны построить строку запроса (которую вы не делаете) и не переводить одиночные апострофы (
'
) в escape-апострофы (''
) (экранированные через входные параметры).В вашей попытке передать «скомпрометированное» значение,
'Male; DROP TABLE tblActor'
строка - это просто обычная строка.Теперь, если вы делаете что-то вроде:
тогда это будет восприимчиво к SQL-инъекции, потому что этот запрос не находится в текущем, предварительно проанализированном контексте; этот запрос - просто еще одна строка на данный момент. Таким образом, значение
@InputParam
может быть,'2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;
и это может представлять проблему, потому что этот запрос будет представлен и выполнен, как:Это одна (из нескольких) основных причин использования хранимых процедур: по своей природе более безопасная (ну, пока вы не обойдете эту безопасность, создавая запросы, как я показал выше, без проверки значений каких-либо используемых параметров). Хотя, если вам нужно построить динамический SQL, предпочтительным способом является его параметризация, используя
sp_executesql
:Используя этот подход, кто - то пытается передать
'2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;
дляDATETIME
входного параметра получить ошибку при выполнении хранимой процедуры. Или даже если хранимая процедура принята@InputParameter
какNVARCHAR(100)
, она должна быть преобразована в aDATETIME
, чтобы перейти к этомуsp_executesql
вызову. И даже если параметр в динамическом SQL является строковым типом, то при входе в хранимую процедуру в первую очередь любой отдельный апостроф автоматически превращается в двойной апостроф.Существует менее известный тип атаки, при котором злоумышленник пытается заполнить поле ввода апострофами, так что строка внутри хранимой процедуры, которая будет использоваться для создания динамического SQL, но которая объявлена слишком маленькой, не может соответствовать всем и выталкивает заключительный апостроф и каким-то образом заканчивается правильным количеством апострофов, чтобы больше не «ускользать» внутри строки. Это называется усечением SQL, о котором говорилось в статье журнала MSDN под названием «Новые атаки с усечением SQL и как их избежать», автор Bala Neerumalla, но эта статья больше не находится в сети. Выпуск, содержащий эту статью - выпуск MSDN Magazine за ноябрь 2006 года - доступен только в виде файла справки Windows (в .chmформат). Если вы загрузите его, он может не открыться из-за настроек безопасности по умолчанию. Если это произойдет, щелкните правой кнопкой мыши файл MSDNMagazineNovember2006en-us.chm и выберите «Свойства». На одной из этих вкладок будет опция «Доверять этому типу файла» (или что-то в этом роде), которую необходимо проверить / включить. Нажмите кнопку «ОК» и попробуйте снова открыть файл .chm .
Еще один вариант атаки усечения заключается в том, что предполагается, что локальная переменная используется для хранения «безопасного» пользовательского значения, поскольку в нем были одинарные кавычки, удвоенные для экранирования, чтобы заполнить эту локальную переменную и поместить одинарные кавычки. в конце. Идея заключается в том, что если локальная переменная имеет неправильный размер, в конце не хватит места для второй одинарной кавычки, оставьте переменную, заканчивающуюся одинарной кавычкой, которая затем объединяется с одинарной кавычкой, которая завершает литеральное значение в динамическом SQL, превращая эту конечную одинарную кавычку во встроенную экранированную одинарную кавычку, а строковый литерал в динамическом SQL затем заканчивается следующей одинарной кавычкой, которая должна была начинать следующий строковый литерал. Например:
Здесь, динамический SQL для выполнения теперь:
Тот же самый динамический SQL в более читаемом формате:
Исправить это легко. Просто выполните одно из следующих действий:
Не используйте локальную переменную для хранения «фиксированного» значения; Просто поместите
REPLACE()
непосредственно в создание динамического SQL:Динамический SQL больше не скомпрометирован:
Замечания о примере Trunction выше:
DELETE tableName
быть разрушительным, но с меньшей вероятностью добавит секретного пользователя или сменит пароль администратора.Для получения более подробной информации, связанной с SQL-инъекцией (охватывающей различные РСУБД и сценарии), см. Следующее в открытом проекте безопасности веб-приложений (OWASP):
Тестирование на SQL-инъекцию
Ответ по переполнению стека по SQL-инъекции и усечению SQL:
Насколько безопасен T-SQL после замены «escape-символа»?
источник
Дело в том, что вы вообще не путаете данные с командой. Значения параметров никогда не рассматриваются как часть команды и, следовательно, никогда не выполняются.
Я написал об этом в блоге по адресу: http://blogs.lobsterpot.com.au/2015/02/10/sql-injection-the-golden-rule/
источник