Dela via


Hantera utlösarsäkerhet

gäller för:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

Som standard körs både DML- och DDL-utlösare i kontexten för den användare som anropar utlösaren. Den som anropar en trigger är den användare som kör instruktionen som gör att triggern körs. Om användaren till exempel Mary kör en DELETE-instruktion som gör att DML-utlösaren DML_trigMary körs, körs koden inuti DML_trigMary i kontexten för användarbehörigheterna för Mary. Det här standardbeteendet kan utnyttjas av användare som vill introducera skadlig kod i databasen eller serverinstansen. Följande DDL-utlösare skapas till exempel av användaren 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

Vad den här utlösaren innebär är att så snart en användare som har behörighet att köra en GRANT CONTROL SERVER-instruktion, till exempel en medlem i sysadmin fast serverroll, kör en ALTER TABLE-instruktion, JohnDoe beviljas CONTROL SERVER behörighet. Med andra ord, även om JohnDoe inte kan ge CONTROL SERVER behörighet till sig själva, aktiverade de utlösarkoden som ger dem den här behörigheten att köra under eskalerade privilegier. Både DML- och DDL-utlösare är öppna för den här typen av säkerhetshot.

Metodtips för utlösare av säkerhet

Du kan vidta följande åtgärder för att förhindra att utlösarkod körs under eskalerade privilegier:

  • Tänk på de DML- och DDL-utlösare som finns i databasen och på serverinstansen genom att fråga efter sys.triggers och sys.server_triggers katalogvyer. Följande fråga returnerar alla DML- och DDL-utlösare på databasnivå i den aktuella databasen och alla DDL-utlösare på servernivå på serverinstansen:

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

    Obs

    Endast sys.triggers är tillgängligt för Azure SQL Database om du inte använder Azure SQL Managed Instance.

  • Tänk på de DML- och DDL-utlösare som finns i databasen genom att göra en fråga på katalogvyn sys.triggers. Följande fråga returnerar alla DML- och DDL-utlösare på databasnivå i den aktuella databasen:

    SELECT type, name, parent_class_desc FROM sys.triggers;
    
  • Använd DISABLE TRIGGER för att inaktivera utlösare som kan skada databasens eller serverns integritet om utlösarna körs under eskalerade privilegier. Följande instruktion inaktiverar alla DDL-utlösare på databasnivå i den aktuella databasen:

    DISABLE TRIGGER ALL ON DATABASE;
    

    Den här instruktionen inaktiverar alla DDL-utlösare på servernivå på serverinstansen:

    DISABLE TRIGGER ALL ON ALL SERVER;
    

    Den här instruktionen inaktiverar alla DML-utlösare i den aktuella databasen:

    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;