Управление безопасностью триггера
Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure
Как триггеры DML, так и триггеры DDL по умолчанию выполняются в контексте того пользователя, который вызывает триггер. Это пользователь, который выполняет инструкцию, вызывающую запуск триггера. Например, если пользователь Mary выполняет инструкцию DELETE, которая запускает триггер DML DML_trigMary , то код внутри DML_trigMary выполняется в контексте прав доступа пользователя Mary. Этим поведением по умолчанию могут воспользоваться те пользователи, которые хотят внести небезопасный код в экземпляр базы данных или сервера. Например, следующий триггер DDL создан пользователем JohnDoe:
CREATE TRIGGER DDL_trigJohnDoe
ON DATABASE
FOR ALTER_TABLE
AS
SET NOCOUNT ON;
BEGIN TRY
EXEC(N'
USE [master];
GRANT CONTROL SERVER TO [JohnDoe];
');
END TRY
BEGIN CATCH
DECLARE @DoNothing INT;
END CATCH;
GO
В этом триггере подразумевается, что как только пользователь с разрешением на выполнение инструкции GRANT CONTROL SERVER
, например член предопределенной роли сервера sysadmin, выполнит инструкцию ALTER TABLE
, пользователь JohnDoe получит разрешение CONTROL SERVER
. Иными словами, хотя JohnDoe не может предоставить CONTROL SERVER
себе разрешение, они включили код триггера, предоставляющий им это разрешение на выполнение при повышенных привилегиях. Эта уязвимость относится как к триггерам DML, так и к триггерам DDL.
Рекомендации по обеспечению безопасности триггеров
Чтобы предотвратить выполнение кода триггера с повышенными правами доступа, примите следующие меры.
Проверьте базу данных и экземпляр сервера на наличие триггеров DDL и DDL. Для этого выполните соответствующие запросы к представлениям каталогов sys.triggers и sys.server_triggers . Следующий запрос возвращает все триггеры DML и DDL уровня базы данных в текущей базе данных, а также все триггеры DDL уровня сервера на экземпляре сервера.
SELECT type, name, parent_class_desc FROM sys.triggers UNION ALL SELECT type, name, parent_class_desc FROM sys.server_triggers;
Примечание.
Только sys.triggers доступно для База данных SQL Azure, если вы не используете Управляемый экземпляр SQL Azure.
Проверьте базу данных на наличие триггеров DDL и DDL. Для этого выполните соответствующие запросы к представлению каталога sys.triggers. Следующий запрос возвращает все триггеры DML и триггеры DDL уровня базы данных в текущей базе данных:
SELECT type, name, parent_class_desc FROM sys.triggers;
С помощью инструкции DISABLE TRIGGER запретите триггеры, которые могут нарушить целостность базы данных или сервера при выполнении с повышенными правами доступа. Следующая инструкция отключает все триггеры DDL уровня базы данных в текущей базе данных:
DISABLE TRIGGER ALL ON DATABASE;
Эта инструкция отключает все триггеры DDL уровня сервера на экземпляре сервера:
DISABLE TRIGGER ALL ON ALL SERVER;
Эта инструкция отключает все триггеры DML в текущей базе данных:
DECLARE @schema_name sysname, @trigger_name sysname, @object_name sysname; DECLARE @sql nvarchar(max); DECLARE trig_cur CURSOR FORWARD_ONLY READ_ONLY FOR SELECT SCHEMA_NAME(schema_id) AS schema_name, name AS trigger_name, OBJECT_NAME(parent_object_id) AS object_name FROM sys.objects WHERE type IN ('TR', 'TA'); OPEN trig_cur; FETCH NEXT FROM trig_cur INTO @schema_name, @trigger_name, @object_name; WHILE @@FETCH_STATUS = 0 BEGIN SELECT @sql = N'DISABLE TRIGGER ' + QUOTENAME(@schema_name) + N'.' + QUOTENAME(@trigger_name) + N' ON ' + QUOTENAME(@schema_name) + N'.' + QUOTENAME(@object_name) + N'; '; EXEC (@sql); FETCH NEXT FROM trig_cur INTO @schema_name, @trigger_name, @object_name; END; GO -- Verify triggers are disabled. Should return an empty result set. SELECT * FROM sys.triggers WHERE is_disabled = 0; GO CLOSE trig_cur; DEALLOCATE trig_cur;