Partilhar via


Gerenciar a segurança do gatilho

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBase de dados SQL no Microsoft Fabric

Por padrão, os gatilhos DML e DDL são executados no contexto do usuário que chama o gatilho. O chamador de um gatilho é o usuário que executa a instrução que faz com que o gatilho seja executado. Por exemplo, se o utilizador Mary executa uma instrução DELETE que faz com que o gatilho DML DML_trigMary seja executado, o código dentro de DML_trigMary é executado no contexto dos privilégios de utilizador de Mary. Esse comportamento padrão pode ser explorado por usuários que desejam introduzir código mal-intencionado no banco de dados ou na instância do servidor. Por exemplo, o seguinte gatilho DDL é criado pelo usuário 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

O que esse gatilho significa é que, assim que um usuário que tem permissão para executar uma instrução GRANT CONTROL SERVER, como um membro da função de servidor fixa sysadmin, executa uma instrução ALTER TABLE, JohnDoe recebe CONTROL SERVER permissão. Em outras palavras, embora JohnDoe não possam conceder CONTROL SERVER permissão a si mesmos, eles habilitaram o código de gatilho que lhes concede essa permissão para executar sob privilégios escalonados. Os gatilhos DML e DDL estão abertos a esse tipo de ameaça à segurança.

Acionar as práticas recomendadas de segurança

Você pode tomar as seguintes medidas para impedir que o código de gatilho seja executado sob privilégios escalonados:

  • Esteja ciente dos gatilhos DML e DDL existentes no banco de dados e na instância do servidor, consulte as visões de catálogo sys.triggers e sys.server_triggers. A consulta a seguir retorna todos os gatilhos DML e DDL no nível de banco de dados no banco de dados atual e todos os gatilhos DDL no nível de servidor na instância do servidor:

    SELECT type, name, parent_class_desc FROM sys.triggers
    UNION ALL
    SELECT type, name, parent_class_desc FROM sys.server_triggers;
    

    Observação

    Somente sys.triggers está disponível para o Banco de Dados SQL do Azure, a menos que você esteja usando a Instância Gerenciada SQL do Azure.

  • Esteja ciente dos gatilhos DML e DDL existentes no banco de dados consultando sys.triggers vista de catálogo. A consulta a seguir retorna todos os gatilhos DML e DDL no nível de banco de dados no banco de dados atual:

    SELECT type, name, parent_class_desc FROM sys.triggers;
    
  • Use DISABLE TRIGGER para desativar triggers que podem prejudicar a integridade da base de dados ou do servidor se os triggers forem executados sob privilégios elevados. A instrução a seguir desabilita todos os gatilhos DDL no nível de banco de dados no banco de dados atual:

    DISABLE TRIGGER ALL ON DATABASE;
    

    Esta instrução desativa todos os gatilhos DDL a nível de servidor na instância de servidor:

    DISABLE TRIGGER ALL ON ALL SERVER;
    

    Esta instrução desativa todos os gatilhos DML no banco de dados atual:

    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;