2008-11-20 4 views
80

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

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

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

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

SELECT * FROM Table WHERE Name = 'a name' 

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

SELECT * FROM Table WHERE Name = @Name 

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

+0

мы должны уточнить, что подразумевается под параметрами (как Джонатан Леффлера указывал) - Я думал, параметры хранимой процедуры, но есть также Parms и {0} Parms? ... – 2008-11-20 21:21:06

+0

Намного проще сказать, мы не используем конкатенацию для построения запроса. – 2008-11-21 03:06:28

+0

Поскольку тег asp.net, я полагаю, что вы создают веб-приложения. В этом случае вам также следует позаботиться о XSS-атаках и, возможно, о других – Spikolynn 2009-01-23 17:18:22

ответ

47

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

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

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

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

+0

. Ключевым моментом является понимание проблемы, поднятой ответом Стива Лоу, также отмеченной в статье @mikekidder. Вы должны быть осторожны везде, где Dynamic SQL есть ли в приложении или на сервере. Динамический SQL опасен, но может быть безопасным. – 2008-11-20 20:51:56

+0

«для злоумышленника не существует способа передать данные, которые будут обрабатываться как« живой »SQL». - Это не совсем так, см. Примеры ниже. – 2008-11-20 21:05:30

+0

Все приведенные ниже примеры определяют «параметризованный запрос» для обозначения параметров принятия кода SQL. Обычное определение - это запрос, который использует вашу базу данных параметров СУБД. Запрещая ошибку СУБД, этот последний метод предотвращает SQL-инъекцию. – RoadWarrior 2008-11-20 21:39:04

10

любого SQL параметр строкового типа (VARCHAR, NVARCHAR и т.д.), который используется для построения динамического запроса по-прежнему уязвим

В противном случае параметр типа преобразования (например, в целом, десятичные, дата и т.д.) Следует исключить любые попытки придать 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-инъекции вектор атаки

6

переполнение буфера не SQL инъекции.

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

1

Это возможно для ХП быть уязвимы для специальных видов инъекции SQL через переливной/усечения, см: Инъекции Включается усечения данных здесь:

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

2

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

12

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

12

В этой теме, по-видимому, есть некоторая путаница в определении «параметризованного запроса».

  • 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(); 
} 
1

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

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

.
1

Вы можете запустить динамический 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'