Gerenciar a segurança dos gatilhos
Por padrão, os gatilhos DML e DDL executam sob o contexto do usuário que aciona o gatilho. O chamador do gatilho é o usuário que executa a instrução que faz com que o gatilho execute. Por exemplo, se o usuário Mary executar uma instrução DELETE que faz com que o gatilho DMLDML_trigMary seja executado, o código dentro do DML_trigMary executará no contexto dos privilégios do usuário para Mary. Esse comportamento padrão pode ser explorado pelos usuários que desejam apresentar um código mal-intencionado no banco de dados ou na instância do servidor. Por exemplo, o gatilho DDL a seguir é criado pelo usuário JohnDoe:
CREATE TRIGGER DDL_trigJohnDoe
ON DATABASE
FOR ALTER_TABLE
AS
GRANT CONTROL SERVER TO JohnDoe ;
GO
O que esse gatilho significa é que assim que um usuário tiver a permissão para executar uma instrução GRANT CONTROL SERVER, como um membro da função de servidor fixa sysadmin, ele executa uma instrução ALTER TABLE, JohnDoe recebe permissão CONTROL SERVER. Em outras palavras, embora JohnDoe não possa conceder permissão CONTROL SERVER para ele mesmo, ele habilita o código do gatilho que lhe concede essa permissão para executar sob privilégios escalados. Os gatilhos DML e DDL estão abertos para este tipo de ameaça à segurança.
Práticas recomendadas para a segurança dos gatilhos
Você pode tomar as medidas a seguir para impedir que o código do gatilho execute sob privilégios escalados:
Lembre-se dos gatilhos DML e DDL que existem no banco de dados e na instância do servidor consultando as exibiçõ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 SELECT type, name, parent_class_desc FROM sys.server_triggers ;
Use DISABLE TRIGGER para desabilitar os gatilhos que podem prejudicar a integridade do banco de dados ou do servidor caso sejam executados sob privilégios escalados. A instrução a seguir desabilita todos os gatilhos DDL no nível do banco de dados no banco de dados atual:
DISABLE TRIGGER ALL ON DATABASE
Essa instrução desabilita todos os gatilhos DDL no nível de servidor na instância do servidor:
DISABLE TRIGGER ALL ON ALL SERVER
Essa instrução desabilita 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 = 'DISABLE TRIGGER ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@trigger_name) + ' ON ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@object_name) + ' ; ' ; 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;