Написание безопасного динамического кода SQL в SQL Server

Скачать ADO.NET

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

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

Схема атаки путем внедрения кода SQL

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Использование олицетворения с помощью предложения EXECUTE AS языка Transact-SQL.

  • Подписывание хранимых процедур с помощью сертификатов.

EXECUTE AS

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

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

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

Перекрестный доступ к базам данных

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

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

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

Ресурс Описание
Хранимые процедуры и Атака путем внедрения кода SQL в электронной документации на SQL Server В этих разделах описывается, как создавать хранимые процедуры и как работает внедрение кода SQL.

Дальнейшие действия