Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
I think most people dealing with SQL Server understand that xp_cmdshell can be a bit of a security hole if not used correctly. But... how do you know it is being used appropriately? Wouldn't it be a nice feature to be able to see exactly who is using xp_cmdshell, when and why?
You can with a SQL Server Audit. SQL Server Audits are built on top of the Extended Events engine, but because they are security related, they cannot be access directly with a
[sql]
CREATE EVENT SESSION ...
[/sql]
syntax. So, how do we do this?.. Here's how:-
First, we create a Server Audit
[sql]
CREATE SERVER AUDIT [xp_cmdshell]
TO FILE (FILEPATH = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Log')
WHERE object_name = 'xp_cmdshell'
GO
[/sql]
Hopefully this is pretty self-explanatory... the Audit log file resides under 'FILEPATH' and the object we are interested in monitoring is
object_name = 'xp_cmdshell'.
ok, cool.
Now we need to create a Server Audit Specification
[sql]
CREATE SERVER AUDIT SPECIFICATION [Audit-xp_cmdshell]
FOR SERVER AUDIT [xp_cmdshell]
ADD (SCHEMA_OBJECT_ACCESS_GROUP),
ADD (AUDIT_CHANGE_GROUP);
GO
[/sql]
The final two steps are to simply enable the specification and the audit:
[sql]
ALTER SERVER AUDIT SPECIFICATION [Audit-xp_cmdshell]
WITH (STATE = ON)
GO
[/sql]
and
[sql]
ALTER SERVER AUDIT [xp_cmdshell]
WITH (STATE = ON)
GO
[/sql]
Now, if any programs try to use 'xp_cmdshell', the audit will track it. So, for my example, I did:
[sql]
sp_configure 'xp_cmdshell',1
reconfigure
GO
EXEC xp_cmdshell 'dir *.exe'
GO
[/sql]
and in my server audit, I get:
and details of:
Nice!... Now to clean up:
[sql]
ALTER SERVER AUDIT [xp_cmdshell]
WITH (STATE = OFF)
GO
ALTER SERVER AUDIT SPECIFICATION [Audit-xp_cmdshell]
WITH (STATE = OFF)
GO
DROP SERVER AUDIT SPECIFICATION [Audit-xp_cmdshell]
GO
DROP SERVER AUDIT [xp_cmdshell]
GO
[/sql]
So, with this approach, we can name and shame the programs using xp_cmdshell thus ensuring we KNOW exactly who, what and when they are doing their work.
How about stopping them from using xp_cmdshell at all? How do we go about that one? Obviously we can disable xp_cmdshell with an sp_configure:
[sql]
sp_configure 'xp_cmdshell', 0
reconfigure
go
[/sql]
But what stops a program / job with sufficient access from simply turning it back on again? How about a Server level trigger:
[sql]
CREATE TRIGGER Audit_XP_CMDSHELL
ON ALL SERVER
FOR ALTER_INSTANCE
AS
BEGIN
DECLARE @SQL NVARCHAR(4000);
SET @SQL = (SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(4000)'));
IF (CHARINDEX('sp_configure', @SQL) > 0) AND (CHARINDEX('xp_cmdshell', @SQL) > 0)
BEGIN
RAISERROR('Attempt to enable xp_cmdshell detected. This operation is denied!', 16, 1) WITH LOG;
ROLLBACK;
END;
END;
[/sql]
Now, the Server level trigger will fire if someone does an ALTER_INSTANCE type command, collect the EVENTDATA() for the event and look inside it to see if an 'sp_configure' command with an 'xp_cmdshell' has been issued. If we match, we rollback the operation and send a copy of the EVENTDATA to the windows event log.
So - now we have tools to put a measure of control around the use of 'xp_cmdshell'. Obviously this is not foolproof - someone with sufficient access rights could disable the Server trigger, use xp_cmdshell, and re-enable the trigger. But hopefully this gives a good idea of what can be accomplished.