Udostępnij za pośrednictwem


Zarządzanie zabezpieczeniami wyzwalacza

Dotyczy:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

Domyślnie wyzwalacze DML i DDL są wykonywane w kontekście użytkownika, który wywołuje wyzwalacz. Obiekt wywołujący wyzwalacz jest użytkownikiem wykonującym instrukcję, która powoduje uruchomienie wyzwalacza. Jeśli na przykład użytkownik Mary wykonuje instrukcję DELETE, która powoduje uruchomienie wyzwalacza DML DML_trigMary, kod wewnątrz DML_trigMary jest wykonywany w kontekście uprawnień użytkownika Mary. To domyślne zachowanie może być wykorzystywane przez użytkowników, którzy chcą wprowadzić złośliwy kod w wystąpieniu bazy danych lub serwera. Na przykład następujący wyzwalacz DDL jest tworzony przez użytkownika 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

Ten wyzwalacz oznacza, że gdy tylko użytkownik, który ma uprawnienia do wykonywania instrukcji GRANT CONTROL SERVER, takiej jak członek sysadmin stałej roli serwera, wykonuje instrukcję ALTER TABLE, JohnDoe otrzymuje uprawnienia CONTROL SERVER. Innymi słowy, chociaż JohnDoe nie może udzielić CONTROL SERVER uprawnień sobie, włączyli kod wyzwalacza, który przyznaje im to uprawnienie do wykonywania z eskalowanymi uprawnieniami. Zarówno wyzwalacze DML, jak i DDL są otwarte dla tego rodzaju zagrożenia bezpieczeństwa.

Wyzwalanie najlepszych rozwiązań w zakresie zabezpieczeń

Aby zapobiec wykonywaniu kodu wyzwalacza w ramach eskalowanych uprawnień, możesz podjąć następujące działania:

  • Należy pamiętać o wyzwalaczach DML i DDL, które istnieją w bazie danych i w wystąpieniu serwera, wysyłając zapytanie do sys.triggers i widoków wykazu sys.server_triggers. Następujące zapytanie zwraca wszystkie wyzwalacze DML i DDL na poziomie bazy danych w bieżącej bazie danych oraz wszystkie wyzwalacze DDL na poziomie serwera w instancji serwera:

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

    Notatka

    Tylko sys.triggers jest dostępna dla usługi Azure SQL Database, chyba że używasz usługi Azure SQL Managed Instance.

  • Należy pamiętać o wyzwalaczach DML i DDL, które istnieją w bazie danych, wysyłając zapytanie do sys.triggers widoku wykazu. Następujące zapytanie zwraca wszystkie wyzwalacze DML i DDL na poziomie bazy danych w bieżącej bazie danych:

    SELECT type, name, parent_class_desc FROM sys.triggers;
    
  • Użyj wyłącz wyzwalacz, aby wyłączyć wyzwalacze, które mogą zaszkodzić integralności bazy danych lub serwera, jeśli wyzwalacze są wykonywane w ramach eskalowanych uprawnień. Poniższa instrukcja wyłącza wszystkie wyzwalacze DDL na poziomie bazy danych w bieżącej bazie danych:

    DISABLE TRIGGER ALL ON DATABASE;
    

    To polecenie wyłącza wszystkie wyzwalacze DDL na poziomie serwera w instancji serwera.

    DISABLE TRIGGER ALL ON ALL SERVER;
    

    Ta instrukcja wyłącza wszystkie wyzwalacze DML w bieżącej bazie danych:

    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;