Написание защищенного динамического SQL-кода в SQL Server (ADO.NET)

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

Любая процедура, создающая инструкции SQL, должна рассматриваться на предмет уязвимости к внедрению небезопасного кода, поскольку SQL Server выполняет все получаемые синтаксически правильные запросы. Даже параметризованные данные могут стать предметом манипуляций опытного и решительного злоумышленника. В случае применения динамического кода SQL следует обязательно параметризовать применяемые команды и никогда не включать значения параметров непосредственно в строку запроса.

Принцип осуществления атаки путем внедрения кода SQL

Атака осуществляется посредством преждевременного завершения текстовой строки и присоединения к ней новой команды. Поскольку к вставленной команде перед выполнением могут быть добавлены дополнительные строки, злоумышленник заканчивает внедряемую строку меткой комментария «--». Весь последующий текст во время выполнения не учитывается. Вставка нескольких команд осуществляется с помощью разделителя — точки с запятой (;).

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

Ниже приведены некоторые полезные рекомендации.

  • Ни в коем случае не следует формировать инструкции Transact-SQL непосредственно на основании данных, введенных пользователем. Используйте хранимые процедуры для проверки ввода данных пользователем.

  • Всегда проверяйте все данные, вводимые пользователем, выполняя проверку типа, длины, формата и диапазона данных. Применяйте функцию QUOTENAME() языка Transact-SQL для экранирования системных имен или функцию REPLACE() для экранирования любого символа в строке.

  • Реализуйте несколько уровней проверки в каждом уровне приложения.

  • Проверяйте размер и тип вводимых данных и устанавливайте соответствующие ограничения. Это поможет предотвратить преднамеренное переполнение буфера.

  • Проверяйте содержимое строковых переменных и принимайте только ожидаемые значения. Отклоняйте записи, содержащие двоичные данные, управляющие последовательности и символы комментариев.

  • При работе с XML-документами проверяйте все вводимые данные на соответствие схеме.

  • В многоуровневых средах все данные должны проверяться перед передачей в доверенную зону.

  • Не допускайте использования в полях следующих строк, из которых могут состоять имена файлов: AUX, CLOCK$, COM1–COM8, CON, CONFIG$, LPT1–LPT8, NUL и PRN.

  • Используйте объекты SqlParameter с хранимыми процедурами и командами для обеспечения контроля типов и проверки длины.

  • Используйте выражения Regex в клиентском коде для фильтрации недопустимых символов.

Стратегии применения динамического кода SQL

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

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

В SQL Server 2005 введены два новых метода предоставления пользователям доступа к данным с помощью хранимых процедур и определяемых пользователем функций, в которых выполняется динамический код SQL.

EXECUTE AS

Предложение EXECUTE AS заменяет разрешения вызывающего объекта разрешениями пользователя, указанного в предложении EXECUTE AS. Вложенные хранимые процедуры или триггеры выполняются в контексте безопасности пользователя-посредника. Это может привести к нарушению работы приложений, которые основаны на использовании средств безопасности уровня строки или требуют аудита. Некоторые функции, возвращающие идентификатор пользователя, возвращают данные о пользователе, указанном в предложении EXECUTE AS, а не данные первоначального вызывающего объекта. Контекст выполнения переходит к вызывающему объекту только после выполнения процедуры или при выполнении инструкции REVERT.

Подписание сертификата

При выполнении хранимой процедуры, подписанной с помощью сертификата, разрешения, предоставленные пользователю сертификата, объединяются с разрешениями вызывающего объекта. Контекст выполнения остается тем же; пользователь сертификата не олицетворяет вызывающий объект. Для подписания хранимых процедур необходимо выполнить несколько действий. После каждого изменения процедуры должно быть проведено ее повторное подписание.

Доступ к объектам в нескольких базах данных

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

Внешние ресурсы

Дополнительные сведения см. в следующих ресурсах.

Ресурс

Описание

Хранимые процедуры и Внедрение кода SQL в электронной документации по SQL Server 2008

Разделы описывают, как создавать хранимые процедуры и как работает внедрение кода SQL.

Хранимые процедуры и Внедрение кода SQL в электронной документации по SQL Server 2005

Разделы описывают, как создавать хранимые процедуры и как работает внедрение кода SQL.

Хранимые процедуры и Использование цепочек владения в электронной документации по SQL Server 2000

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

Новые виды атак по принципу отсечения SQL и их предотвращение в журнале MSDN Magazine.

Описание того, как происходит разграничение символов и строк, внедрение кода SQL и модификация с применением атак по принципу отсечения.

См. также

Основные понятия

Сценарии защиты приложений в SQL Server (ADO.NET)

Управление разрешениями с помощью хранимых процедур в SQL Server (ADO.NET)

Подписывание хранимых процедур в SQL Server (ADO.NET)

Настройка разрешений с олицетворением в SQL Server (ADO.NET)

Другие ресурсы

Защита приложений ADO.NET

Общие сведения о безопасности SQL Server (ADO.NET)