Как избежать простых SQL-запросов в C# для SqlServer
Я использую API, который ожидает строку SQL. Я беру пользовательский ввод, экранирую его и передаю его в API. Пользовательский ввод довольно прост. Он запрашивает значения столбцов. Вот так:
string name = userInput.Value;
затем я создаю SQL-запрос:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
name.replace("'", "''"));
Это достаточно безопасно? Если это не так, есть ли простая библиотечная функция, которая делает значения столбцов безопасными:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
SqlSafeColumnValue(name));
API использует SQLServer в качестве базы данных.
7 ответов:
поскольку использование SqlParameter не является опцией, просто замените ' на " (это две одинарные кавычки, а не одна двойная кавычка) в строковых литералах. Вот и все.
для потенциальных downvoters: перечитайте первую строку вопроса. "Использовать параметры" - это тоже была моя внутренняя реакция.
EDIT: да, я знаю об атаках SQL-инъекций. Если вы считаете, что это цитирование уязвимо для них, пожалуйста, предоставьте рабочий контрпример. Я думаю, что это не так.
я использовал динамический sql (я слышу, как расстрельная команда заряжает свои винтовки) для функциональности поиска, но он сломался бы всякий раз, когда пользователь искал кого-то с фамилией, такой как "O'Reilly".
мне удалось найти обходной путь (читай "hack"):
создал скалярную функцию в sql, которая заменила одинарную кавычку двумя одинарными кавычками, эффективно избегая оскорбительной одинарной кавычки, поэтому
"...Фамилия вроде '%O'Reilly% ' и..." становится "...Фамилия вроде '%O 'Reilly%' AND..."эта функция вызывается из sql всякий раз, когда я подозреваю, что поля могут содержать один символ кавычки ie: firstname, lastname.
CREATE FUNCTION [dbo].[fnEscapeSingleQuote] (@StringToCheck NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN DECLARE @Result NVARCHAR(MAX) SELECT @Result = REPLACE(@StringToCheck, CHAR(39), CHAR(39) + CHAR(39)) RETURN @Result END
Не очень элегантное, но оно работает, когда вы находитесь в крайнем случае.
можно заменить " на " Вместо параметризации при необходимости решения проблемы в большом количестве ad hoc sql за короткое время с минимальным риском поломки и минимальным тестированием.
лучше всего использовать параметры SQL, но тогда у вас есть ограничение на 2300 параметров для запроса. В большинстве случаев этого будет более чем достаточно. Но в редких случаях, когда вы превышаете этот предел, я рассматриваю это как вариант.
SqlCommand и Entity Framework используют
exec sp_executesql...
.таким образом, действительно есть альтернатива необработанным строкам с вашим собственным шаблоном экранирования. С помощью SqlCommand вы технически используете параметризованные запросы, но вы обходите ADO.Net абстракция базового кода SQL.
поэтому, хотя ваш код не предотвращает SQL-инъекцию, конечным ответом является sp_executesql, а не SqlCommand.
сказав это, я уверен, что есть специальная обработка требования для создания строки, защищенной от инъекций SQL, которая использует sp_executesql.
посмотреть: как вернуть значения из динамической хранимой процедуры SQL в Entity Framework?