Управление безопасностью триггеров

Как триггеры DML, так и триггеры DDL по умолчанию выполняются в контексте того пользователя, который вызывает триггер. Это пользователь, который выполняет инструкцию, вызывающую запуск триггера. Например, если пользователь Mary выполняет инструкцию DELETE, которая запускает триггер DML DML_trigMary, то код внутри DML_trigMary выполняется в контексте прав доступа пользователя Mary. Этим поведением по умолчанию могут воспользоваться те пользователи, которые хотят внести небезопасный код в экземпляр базы данных или сервера. Например, следующий триггер DDL создан пользователем JohnDoe:

CREATE TRIGGER DDL_trigJohnDoe

ON DATABASE

FOR ALTER_TABLE

AS

GRANT CONTROL SERVER TO JohnDoe ;

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
    SELECT type, name, parent_class_desc FROM sys.server_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 = 'DISABLE TRIGGER ' + QUOTENAME(@schema_name) + '.'
            + QUOTENAME(@trigger_name) +
            ' ON ' + QUOTENAME(@schema_name) + '.' 
            + QUOTENAME(@object_name) + ' ; ' ;
        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;
    

См. также

Справочник

CREATE TRIGGER (Transact-SQL)

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

Триггеры DML

Триггеры DDL