Delen via


Triggerbeveiliging beheren

Van toepassing op:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

Standaard worden zowel DML- als DDL-triggers uitgevoerd onder de context van de gebruiker die de trigger aanroept. De aanroeper van een trigger is de gebruiker die de instructie uitvoert die ervoor zorgt dat de trigger wordt uitgevoerd. Als gebruiker Mary bijvoorbeeld een DELETE-instructie uitvoert waardoor DML-trigger DML_trigMary wordt uitgevoerd, wordt de code in DML_trigMary uitgevoerd in de context van de gebruikersbevoegdheden voor Mary. Dit standaardgedrag kan worden misbruikt door gebruikers die schadelijke code willen introduceren in de database of serverinstantie. De volgende DDL-trigger wordt bijvoorbeeld gemaakt door gebruiker 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

Wat deze trigger betekent, is dat zodra een gebruiker die gemachtigd is om een GRANT CONTROL SERVER instructie uit te voeren, zoals een lid van de vaste serverrol sysadmin, een ALTER TABLE instructie uitvoert, JohnDoe toestemming krijgt.CONTROL SERVER Met andere woorden, hoewel JohnDoe geen toestemming voor zichzelf kan verlenen CONTROL SERVER , hebben ze de triggercode ingeschakeld waarmee ze deze machtiging krijgen om uit te voeren onder geëscaleerde bevoegdheden. Zowel DML- als DDL-triggers zijn open voor dit soort beveiligingsrisico's.

Aanbevolen procedures voor triggerbeveiliging

U kunt de volgende maatregelen nemen om te voorkomen dat triggercode wordt uitgevoerd onder geëscaleerde bevoegdheden:

  • Let op de DML- en DDL-triggers die aanwezig zijn in de database en op het serverexemplaren door query's uit te voeren op de sys.triggers en sys.server_triggers catalogusweergaven. De volgende query retourneert alle DML- en databaseniveau DDL-triggers in de huidige database en alle DDL-triggers op serverniveau op het serverexemplaren:

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

    Opmerking

    Alleen sys.triggers zijn beschikbaar voor Azure SQL Database, tenzij u Azure SQL Managed Instance gebruikt.

  • Let op de DML- en DDL-triggers die aanwezig zijn in de database door een query uit te voeren op de catalogusweergave sys.triggers . Met de volgende query worden alle DML- en DDL-triggers op databaseniveau in de huidige database geretourneerd:

    SELECT type, name, parent_class_desc FROM sys.triggers;
    
  • Gebruik DISABLE TRIGGER om triggers uit te schakelen die de integriteit van de database of server kunnen schaden als de triggers worden uitgevoerd onder geëscaleerde bevoegdheden. Met de volgende instructie worden alle DDL-triggers op databaseniveau in de huidige database uitgeschakeld:

    DISABLE TRIGGER ALL ON DATABASE;
    

    Met deze instructie worden alle DDL-triggers op serverniveau uitgeschakeld op het serverexemplaren:

    DISABLE TRIGGER ALL ON ALL SERVER;
    

    Met deze instructie worden alle DML-triggers in de huidige database uitgeschakeld:

    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;