Написание безопасного динамического кода SQL в SQL Server
Внедрение кода 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. |
Дальнейшие действия
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по