Gestire la sicurezza del trigger
Si applica a: SQL Server database SQL di Azure Istanza gestita di SQL di Azure
Per impostazione predefinita, i trigger DML e DDL vengono eseguiti nel contesto dell'utente che li chiama. Il chiamante di un trigger è l'utente che esegue l'istruzione che causa l'esecuzione del trigger. Se ad esempio l'utente Mary esegue un'istruzione DELETE che causa l'esecuzione del trigger DML DML_trigMary , il codice all'interno di DML_trigMary viene eseguito nel contesto dei privilegi utente relativi a Mary. Il funzionamento predefinito può essere sfruttato dagli utenti che desiderano introdurre malware nel database o nell'istanza del server. Ad esempio, il trigger DDL seguente viene creato dall'utente 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
Il trigger indica che non appena un utente autorizzato a eseguire un'istruzione GRANT CONTROL SERVER
, ad esempio un membro del ruolo predefinito del server sysadmin, esegue un'istruzione ALTER TABLE
, all'utente JohnDoe viene concessa l'autorizzazione CONTROL SERVER
. In altre parole, anche se JohnDoe non può concedere CONTROL SERVER
l'autorizzazione a se stesso, ha abilitato il codice del trigger che gli concede tale autorizzazione per l'esecuzione con privilegi aumentati. I trigger DML e DDL sono esposti a questo tipo di minaccia per la sicurezza.
Procedure consigliate per la sicurezza dei trigger
Per impedire l'esecuzione del codice del trigger con privilegi alzati di livello, è possibile adottare le misure seguenti:
Individuare i trigger DML e DDL esistenti nel database e nell'istanza del server eseguendo query sulle viste del catalogo sys.triggers e sys.server_triggers . La query seguente restituisce tutti i trigger DML e DDL a livello di database nel database corrente e tutti i trigger DDL a livello di server nell'istanza del server:
SELECT type, name, parent_class_desc FROM sys.triggers UNION ALL SELECT type, name, parent_class_desc FROM sys.server_triggers;
Nota
Per il database SQL di Azure è disponibile solo sys.triggers a meno che non si usi l'istanza gestita di SQL di Azure.
Individuare i trigger DML e DDL esistenti nel database eseguendo query sulla vista del catalogo sys.triggers. La query seguente restituisce tutti i trigger DML e DDL a livello di database nel database corrente:
SELECT type, name, parent_class_desc FROM sys.triggers;
Per disabilitare i trigger che possono compromettere l'integrità del database o del server se vengono eseguiti con privilegi alzati di livello, usare DISABLE TRIGGER . L'istruzione seguente disabilita tutti i trigger DDL a livello di database nel database corrente:
DISABLE TRIGGER ALL ON DATABASE;
L'istruzione seguente disabilita tutti i trigger DDL a livello di server nell'istanza del server:
DISABLE TRIGGER ALL ON ALL SERVER;
L'istruzione seguente disabilita tutti i trigger DML nel database corrente:
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;