Достаточно ли параметров для предотвращения инъекций Sql? - PullRequest
81 голосов
/ 20 ноября 2008

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

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

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

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

SELECT * FROM Table WHERE Name = 'a name'

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

SELECT * FROM Table WHERE Name = @Name

и затем установите значение параметра @Name для объекта запроса / команды.

Ответы [ 9 ]

48 голосов
/ 20 ноября 2008

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

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

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

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

12 голосов
/ 21 ноября 2008

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

  • 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();
}
12 голосов
/ 20 ноября 2008

Нет, риск внедрения 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, это более сложная проблема.

10 голосов
/ 20 ноября 2008

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

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

РЕДАКТИРОВАТЬ: пример, где параметр @ 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-инъекций;

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

6 голосов
/ 20 ноября 2008

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

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

2 голосов
/ 20 ноября 2008

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

1 голос
/ 12 апреля 2011

Вы можете запустить динамический 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'
1 голос
/ 22 июля 2009

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

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

1 голос
/ 20 ноября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...