Достаточно ли параметров для предотвращения инъекций Sql?

Я проповедовал как своим коллегам, так и здесь, о том, насколько хорошо использовать параметры в SQL-запросах, особенно в .NET-приложениях. Я даже зашел так далеко, что обещал им предоставить иммунитет против атак SQL-инъекций.

Но я начинаю задаваться вопросом, действительно ли это так. Существуют ли какие-либо известные атаки SQL-инъекций, которые будут успешными против параметризованного запроса? Можете ли вы, например, отправить строку, которая вызывает переполнение буфера на сервере?

Разумеется, есть и другие соображения, чтобы гарантировать, что веб-приложение безопасно (например, санировать ввод пользователя и все это), но теперь я думаю о SQL-инъекциях. Меня особенно интересуют атаки на MsSQL 2005 и 2008, поскольку они являются моими основными базами данных, но все базы данных интересны.

Изменить: уточнить, что я подразумеваю под параметрами и параметризованными запросами. Используя параметры, я имею в виду использование "переменных" вместо того, чтобы строить sql-запрос в строке.
Поэтому вместо этого:

SELECT * FROM Table WHERE Name = 'a name'

Мы делаем это:

SELECT * FROM Table WHERE Name = @Name

а затем установите значение параметра @Name в объекте query/command.

Ответ 1

Заместители достаточны для предотвращения инъекций. Вы все еще можете быть открыты для переполнения буфера, но это совершенно другой аромат атаки от SQL-инъекции (вектор атаки не будет синтаксисом SQL, а двоичным). Поскольку переданные параметры будут экранированы должным образом, злоумышленник не сможет передать данные, которые будут обрабатываться как "живой" SQL.

Вы не можете использовать функции внутри заполнителей, и вы не можете использовать заполнители в качестве имен столбцов или таблиц, потому что они экранированы и цитируются как строковые литералы.

Однако, если вы используете параметры как часть конкатенации строк внутри динамического запроса, вы все равно уязвимы для инъекций, потому что ваши строки не будут экранированы, но будут быть буквальным. Использование других типов параметров (например, целое число) безопасно.

Тем не менее, если вы используете ввод использования для установки значения чего-то вроде security_level, тогда кто-то может просто сделать себя администраторами в вашей системе и иметь бесплатное для всех. Но это просто базовая проверка ввода и не имеет никакого отношения к SQL-инъекции.

Ответ 3

Нет, все равно существует риск внедрения SQL при каждом интерполяции неутвержденных данных в SQL-запрос.

Параметры запроса помогают избежать этого риска, разделив литеральные значения из синтаксиса SQL.

'SELECT * FROM mytable WHERE colname = ?'

Это хорошо, но есть и другие цели интерполяции данных в динамический SQL-запрос, который не может использовать параметры запроса, потому что это не значение SQL, а вместо этого имя таблицы, имя столбца, выражение или какой-либо другой синтаксис.

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

Не имеет значения, используете ли вы хранимые процедуры или выполняете динамические SQL-запросы непосредственно из кода приложения. Риск все еще существует.

Средством в этих случаях является использование FIEO по мере необходимости:

  • Ввод фильтра: проверяйте, чтобы данные выглядели как законные целые числа, имена таблиц, имена столбцов и т.д., прежде чем их интерполировать.

  • Выход Escape:, в этом случае "вывод" означает перенос данных в SQL-запрос. Мы используем функции для преобразования переменных, используемых в качестве строковых литералов в выражении SQL, так что метки кавычек и другие специальные символы внутри строки экранируются. Мы также должны использовать функции для преобразования переменных, которые будут использоваться в качестве имен таблиц, имен столбцов и т.д. Что касается другого синтаксиса, например динамического написания всего выражения SQL, это более сложная проблема.

Ответ 4

В этом потоке, похоже, есть путаница в определении "параметризованного запроса".

  • SQL, такой как хранимый процесс, который принимает параметры.
  • SQL, который вызывается с использованием набора параметров СУБД.

Учитывая прежнее определение, многие ссылки показывают рабочие атаки.

Но "нормальное" определение является последним. Учитывая это определение, я не знаю об атаке SQL-инъекций, которая будет работать. Это не означает, что его нет, но я еще не видел его.

Из комментариев я недостаточно выражаю себя, поэтому вот пример, который, надеюсь, будет более ясным:

Этот подход открыт для SQL-инъекций

exec dbo.MyStoredProc 'DodgyText'

Этот подход не открыт для SQL-инъекции

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

Ответ 5

любой sql-параметр строкового типа (varchar, nvarchar и т.д.), который используется для построения динамического запроса, все еще уязвим

в противном случае преобразование типа параметра (например, в int, decimal, date и т.д.) должно исключить любую попытку ввода sql через параметр

EDIT: пример, где параметр @p1 предназначен для имени таблицы

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

Если @p1 выбран из раскрывающегося списка, это потенциальный вектор атаки sql-injection;

Если @p1 сформулировано программно с возможностью вмешательства пользователя, то это не потенциальный вектор атаки sql-injection

Ответ 6

Переполнение буфера не является инъекцией SQL.

Параметризированные запросы гарантируют вам безопасность от SQL-инъекций. Они не гарантируют, что в вашем SQL-сервере нет возможных эксплойтов в виде ошибок, но это ничего не гарантирует.

Ответ 7

Ваши данные небезопасны, если вы используете динамический sql в любой форме или форме, потому что разрешения должны быть на уровне таблицы. Да, вы ограничили тип и количество инъекционных атак из этого конкретного запроса, но не ограничиваетесь доступом, который может получить пользователь, если он или она найдет способ войти в систему, и вы полностью лишены внутренних пользователей, получающих доступ к тем, что им не нужно в чтобы совершить мошенничество или украсть личную информацию для продажи. Динамический SQL любого типа - опасная практика. Если вы используете нединамические хранимые procs, вы можете установить разрешения на уровне procesdure, и ни один пользователь не сможет ничего сделать, кроме того, что определено procs (за исключением системных админов, конечно).

Ответ 8

Возможно, что сохраненный proc будет уязвим для специальных типов SQL-инъекций посредством переполнения/усечения, см.: Injection Enabled посредством Data Truncation здесь:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

Ответ 9

Просто помните, что с параметрами вы можете легко сохранить строку или указать имя пользователя, если у вас нет каких-либо политик "); пользователи с разделителями таблиц -"

Это само по себе не наносит вреда, но вы лучше знаете, где и как эта дата используется дальше в вашем приложении (например, хранится в файле cookie, который впоследствии извлекается для выполнения других действий.

Ответ 10

У меня был только первый опыт использования атаки SQL Injection. Это боль в очистке, поэтому нет такой вещи, как слишком большая безопасность, если она не мешает функциям. Я полагаю, что приложение пришло через хранимую процедуру и задалось вопросом, есть ли у кого-нибудь из бокового решения для дезинфекции данных, поступающих в хранимую процедуру paramater?

Ответ 12

Вы можете запустить динамический sql в качестве примера

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'