SQL Server DDL安全審計

來源:互聯網
上載者:User

應用情境:

        作為SQL Server安全審計的一部分,DBA可能需要這樣的一份報吿:知道哪些資料庫物件(儲如表、預存程序、視圖、使用者、函數、使用者權限等等)在什麼時候被誰修改過,以及修改的內容等等。也還可能需要一份預存程序、函數以及視圖的代碼修改曆史清單,知道這些代碼在去過某段時間裡被修改。那麼,下面這份代碼正好是你所需要的。

        此代碼在SQL Server 2005/2008運行良好。

1.      建立一個審計資料庫,專門用於存放審計記錄;

此步驟略。審計資料庫名為:AuditDB;

 

2.      建立一個審計使用者,用於實施審計時所需要的許可權;

CREATE LOGIN[AuditUser]WITH PASSWORD=N'123',DEFAULT_DATABASE=[AuditDB]GOuse AuditDBGOCREATE USERAudituserFOR LOGIN Audituser;GOALTER LOGIN[AuditUser]DISABLEGO

註:該使用者無需登入,所以可以禁用此使用者的登入。


3.      在審計資料庫AuditDB上建立下如下審計表:

表1:DBA_ChangedObjectLog(審計主表)

表2:DBA_ChangedObjectText(審計從表) 


註: 

審計主表與審計從表之間的關聯欄位是LogID;

只有視圖、預存程序、函數、觸發器才有從表資料,因為只有這些對象才有代碼定義;

 

4.      為審計使用者AuditUser授權:

use mastergogrant viewserverstate to Audituseruse AuditDBgogrant insertonDBA_ChangedObjectLogtoAuditusergrant insertonDBA_ChangedObjectTexttoAudituser


5.      為所有可以修改資料庫物件的使用者,授予類比AuditUser的許可權:

如果你不這麼做,那你就必須為所有這些使用者分別授予第四步中AuditUser的許可權;

grant impersonateonlogin::user1toauditusergrant impersonateonlogin::auditusertouser1

如果你的資料庫中已經有幾十上百或上千的使用者,那你可以用如下語句產生的程式碼大量授權:

select 'grant impersonate on login::['+[name]+'] to audituser'fromsys.server_principalswhere type='S'andname<>'audituser'union allselect 'grant impersonate onlogin::audituser to ['+[name]+']'fromsys.server_principalswhere type='S'andname<>'audituser'

註:以對後建立的每個使用者,也必須這樣授權。

 

6.      在審計主表上建立觸發器tr_Dba_ObjectChangeLog_insert。

此觸發器的目的是獲得當前修改的資料庫物件(視圖、預存程序、函數、觸發器)代碼定義並儲存入從表中。

USE [AuditDB]GOSET ANSI_NULLSONGOSET QUOTED_IDENTIFIERONGO --在審計主表上建立觸發器:ALTER trigger[dbo].[tr_Dba_ObjectChangeLog_insert]on [dbo].[DBA_ChangedObjectLog]for insertasbegin    declare       @Logid uniqueidentifier,       @DatabaseNamenvarchar(256),       @UserNamenvarchar(256),       @SchemaNamenvarchar(256),       @ObjectNamenvarchar(256),       @ObjectTypenvarchar(256),       --@original_usernvarchar(256),       @EventTypenvarchar(256),       @sql nvarchar(256),       @IsaDDLTriggerint        execute as login =original_login()        set @IsaDDLTrigger= -1       select @Logid=logid,@DatabaseName=DatabaseName,@SchemaName=SchemaName,@ObjectName=ObjectName,@ObjectType=ObjectType,@UserName=UserName,@EventType=EventType       from inserted;        if  @ObjectType not in('PROCEDURE','VIEW','FUNCTION','TRIGGER') return;       if @EventType like 'DROP%'return;        set @sql = N'select @IsaDDLTriggerOut=count(*) from ['+@DatabaseName+'].sys.triggers where name='''+@ObjectName+''' and parent_class=0';       execute sp_executesql@sql,N'@IsaDDLTriggerOut int OUTPUT',@IsaDDLTriggerOut=@IsaDDLTriggerOUTPUT;        --DDL觸發器不能使用sp_helptext獲得它的文本       if @IsaDDLTrigger>0 return;            if object_id('tempdb..#temp')isnot null           drop table #temp        create table #temp(           [Line][int]IDENTITY(1,1)NOTNULL,           [LineText]varchar(max)       )        set @sql='insert into #temp exec ['+@DatabaseName+'].dbo.sp_helptext '''+@SchemaName+'.'+@ObjectName+'''';       exec (@sql)          execute as caller       insert into dbo.Dba_ChangedObjectText       select @Logid,@DatabaseName,@SchemaName,@ObjectName,[Line],[LineText]from#temp        drop table #temp end


7.      在要實施審計的資料庫上建立觸發器tr_dba_Trace_ObjectChangeLog:

建立之前,需要對要實施審計的資料庫如下配置。例如你需要對資料庫TEST進行DDL審計,則:

alter database[TEST]set trustworthy on

然後再建立觸發器tr_dba_Trace_ObjectChangeLog

USE [TEST]GOSET ANSI_NULLSONGOSET QUOTED_IDENTIFIERONGOCREATE trigger[tr_dba_Trace_ObjectChangeLog]on database--withexecute as 'AuditUser'for ddl_table_events,ddl_view_events,ddl_index_events,    ddl_synonym_events,ddl_function_events,ddl_procedure_events,ddl_trigger_events,     ddl_database_security_events--,ddl_rule_events  asbegin    set nocount on     declare       @newid UNIQUEIDENTIFIER,        @data xml,       @spid smallint,       @LoginNamevarchar(256),       @ProgramNamevarchar(256),       @IP varchar(15),       @mac varchar(12),       @EventTypevarchar(50),       @ObjectTypevarchar(25),       @ObjectNamevarchar(256),       @IsaDDLTriggerint,       @Line smallint     set @newid = newid()    set @data = EVENTDATA()    set @spid = @data.value('(/EVENT_INSTANCE/SPID)[1]','smallint')    set @EventType = @data.value('(/EVENT_INSTANCE/EventType)[1]','varchar(50)')    set @ObjectType = @data.value('(/EVENT_INSTANCE/ObjectType)[1]','varchar(25)')    set @ObjectName = @data.value('(/EVENT_INSTANCE/ObjectName)[1]','varchar(256)')    set @LoginName = @data.value('(/EVENT_INSTANCE/LoginName)[1]','varchar(256)')    --set @ObjectName= @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'varchar(256)')    set @mac =(SELECTNET_ADDRESSFROM master.dbo.sysprocessesWHEREspid = @spid)    set @Line = 0     --過濾掉由維護計劃產生的重建索引記錄(因此類記錄太龐大)    if @LoginName='NT AUTHORITY\SYSTEM'and@ObjectType= 'INDEX'       return;     -- if the objectis a ddl trigger    if (selectcount(*)from sys.triggerswherename=@ObjectNameandparent_class=0)= 0       set @IsaDDLTrigger = 0    else set @IsaDDLTrigger = 1     execute as login ='AuditUser'     select @ProgramName=[Program_Name]fromsys.dm_exec_sessionswheresession_id=@spid    select @IP=client_net_addressfromsys.dm_exec_connectionswheresession_id=@spid     insert into DBAdminPlat.dbo.DBA_ChangedObjectLog(       [LogId],       [EventType],[PostTime],[SPID],[ServerName],[Host_IP_Address],[Host_MAC_Address],       [ProgramName],[LoginName],[UserName],[DatabaseName],[SchemaName],       [ObjectName],[ObjectType],[TSQLCommand]--,[EventDate]    )    values(       @newid,       @EventType,       @data.value('(/EVENT_INSTANCE/PostTime)[1]','datetime'),       @spid,       @data.value('(/EVENT_INSTANCE/ServerName)[1]','varchar(256)'),       @IP,       @mac,       @ProgramName,       @LoginName,--@data.value('(/EVENT_INSTANCE/LoginName)[1]','varchar(256)'),       @data.value('(/EVENT_INSTANCE/UserName)[1]','varchar(256)'),       @data.value('(/EVENT_INSTANCE/DatabaseName)[1]','varchar(256)'),       @data.value('(/EVENT_INSTANCE/SchemaName)[1]','varchar(256)'),       @ObjectName,       @ObjectType,       --For objectslike procs, views, triggers and functions ,text of which will be stored inmaster.[dbo].[tb_dba_ChangedObjectText] table.       case when @ObjectType in('PROCEDURE','VIEW','FUNCTION','TRIGGER')and(@EventType<>'GRANT_DATABASE'or@EventType like 'DROP%')and@IsaDDLTrigger=0           then null else @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]','varchar(max)')end    );     REVERT; endGO SET ANSI_NULLSOFFGOSET QUOTED_IDENTIFIEROFFGOENABLE TRIGGER[tr_dba_Trace_ObjectChangeLog]ON DATABASEGO

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.