Skip to content

Commit 3900d6e

Browse files
Add some permissions checks to sp_Blitz
Closes #3292 This feels like a somewhat naïve set of checks. I don't know a ton about security. It may clash when someone uses `EXECUTE AS` or signs the procedure for execution for lower-privileged users. It's also incomplete at the moment, because I need to round up commands that touch system databases we may not have read permissions in. I fully expect this to get rejected, but it got me error-free runs in a tightly locked down SQL Server environment. If anyone has feedback, I'm happy to take it.
1 parent 11ac1d4 commit 3900d6e

1 file changed

Lines changed: 230 additions & 49 deletions

File tree

sp_Blitz.sql

Lines changed: 230 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,128 @@ AS
186186
,@CurrentComponentVersionCheckModeOK BIT
187187
,@canExitLoop BIT
188188
,@frkIsConsistent BIT
189-
,@NeedToTurnNumericRoundabortBackOn BIT;
189+
,@NeedToTurnNumericRoundabortBackOn BIT
190+
,@sa bit = 1
191+
,@SUSER_NAME sysname = SUSER_SNAME()
192+
,@SkipDBCC bit = 0
193+
,@SkipTrace bit = 0
194+
,@SkipXPRegRead bit = 0
195+
,@SkipXPFixedDrives bit = 0
196+
,@SkipXPCMDShell bit = 0
197+
,@SkipMaster bit = 0
198+
,@SkipMSDB bit = 0
199+
,@SkipModel bit = 0
200+
,@SkipTempDB bit = 0
201+
,@SkipValidateLogins bit = 0;
202+
203+
DECLARE
204+
@db_perms table
205+
(
206+
database_name sysname,
207+
permission_name sysname
208+
);
209+
190210

191211
/* End of declarations for First Responder Kit consistency check:*/
192212
;
193213

214+
/*Starting permissions checks here, but only if we're not a sysadmin*/
215+
IF
216+
(
217+
SELECT
218+
sa =
219+
ISNULL
220+
(
221+
IS_SRVROLEMEMBER(N'sysadmin'),
222+
0
223+
)
224+
) = 0
225+
BEGIN
226+
SET @sa = 0; /*Setting this to 0 to skip DBCC COMMANDS*/
227+
228+
IF NOT EXISTS
229+
(
230+
SELECT
231+
1/0
232+
FROM sys.fn_my_permissions(NULL, NULL) AS fmp
233+
WHERE fmp.permission_name = N'VIEW SERVER STATE'
234+
)
235+
BEGIN
236+
RAISERROR('The user %s does not have VIEW SERVER STATE permissions.', 0, 11, @SUSER_NAME) WITH NOWAIT;
237+
RETURN;
238+
END; /*If we don't have this, we can't do anything at all.*/
239+
240+
IF NOT EXISTS
241+
(
242+
SELECT
243+
1/0
244+
FROM fn_my_permissions(N'sys.traces', N'OBJECT') AS fmp
245+
WHERE fmp.permission_name = N'ALTER'
246+
)
247+
BEGIN
248+
SET @SkipTrace = 1;
249+
END; /*We need this permission to execute trace stuff, apparently*/
250+
251+
IF NOT EXISTS
252+
(
253+
SELECT
254+
1/0
255+
FROM fn_my_permissions(N'xp_regread', N'OBJECT') AS fmp
256+
WHERE fmp.permission_name = N'EXECUTE'
257+
)
258+
BEGIN
259+
SET @SkipXPRegRead = 1;
260+
END; /*Need execute on xp_regread*/
261+
262+
IF NOT EXISTS
263+
(
264+
SELECT
265+
1/0
266+
FROM fn_my_permissions(N'xp_fixeddrives', N'OBJECT') AS fmp
267+
WHERE fmp.permission_name = N'EXECUTE'
268+
)
269+
BEGIN
270+
SET @SkipXPFixedDrives = 1;
271+
END; /*Need execute on xp_fixeddrives*/
272+
273+
IF NOT EXISTS
274+
(
275+
SELECT
276+
1/0
277+
FROM fn_my_permissions(N'xp_cmdshell', N'OBJECT') AS fmp
278+
WHERE fmp.permission_name = N'EXECUTE'
279+
)
280+
BEGIN
281+
SET @SkipXPCMDShell = 1;
282+
END; /*Need execute on xp_cmdshell*/
283+
284+
IF NOT EXISTS
285+
(
286+
SELECT
287+
1/0
288+
FROM fn_my_permissions(N'sp_validatelogins', N'OBJECT') AS fmp
289+
WHERE fmp.permission_name = N'EXECUTE'
290+
)
291+
BEGIN
292+
SET @SkipValidateLogins = 1;
293+
END; /*Need execute on sp_validatelogins*/
294+
295+
INSERT
296+
@db_perms
297+
(
298+
database_name,
299+
permission_name
300+
)
301+
SELECT
302+
database_name =
303+
DB_NAME(d.database_id),
304+
fmp.permission_name
305+
FROM sys.databases AS d
306+
CROSS APPLY fn_my_permissions(d.name, 'DATABASE') AS fmp
307+
WHERE fmp.permission_name = N'SELECT'
308+
AND d.database_id < 5; /*Databases where we don't have read permissions*/
309+
END;
310+
194311
SET @crlf = NCHAR(13) + NCHAR(10);
195312
SET @ResultText = 'sp_Blitz Results: ' + @crlf;
196313

@@ -331,6 +448,66 @@ AS
331448
OR LOWER(d.name) IN ('dbatools', 'dbadmin', 'dbmaintenance'))
332449
OPTION(RECOMPILE);
333450

451+
/*Skip checks for database where we don't have read permissions*/
452+
INSERT INTO
453+
#SkipChecks
454+
(
455+
DatabaseName
456+
)
457+
SELECT
458+
DB_NAME(d.database_id)
459+
FROM sys.databases AS d
460+
WHERE NOT EXISTS
461+
(
462+
SELECT
463+
1/0
464+
FROM @db_perms AS dp
465+
WHERE dp.database_name = DB_NAME(d.database_id)
466+
);
467+
468+
/*Skip individial checks where we don't have permissions*/
469+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
470+
SELECT
471+
v.*
472+
FROM (VALUES(NULL, NULL, 29)) AS v (DatabaseName, CheckID, ServerName) /*Looks for user tables in model*/
473+
WHERE NOT EXISTS (SELECT 1/0 FROM @db_perms AS dp WHERE dp.database_name = 'model');
474+
475+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
476+
SELECT
477+
v.*
478+
FROM (VALUES(NULL, NULL, 68)) AS v (DatabaseName, CheckID, ServerName) /*DBCC command*/
479+
WHERE @sa = 0;
480+
481+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
482+
SELECT
483+
v.*
484+
FROM (VALUES(NULL, NULL, 69)) AS v (DatabaseName, CheckID, ServerName) /*DBCC command*/
485+
WHERE @sa = 0;
486+
487+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
488+
SELECT
489+
v.*
490+
FROM (VALUES(NULL, NULL, 92)) AS v (DatabaseName, CheckID, ServerName) /*xp_fixeddrives*/
491+
WHERE @SkipXPFixedDrives = 1;
492+
493+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
494+
SELECT
495+
v.*
496+
FROM (VALUES(NULL, NULL, 211)) AS v (DatabaseName, CheckID, ServerName) /*xp_regread*/
497+
WHERE @SkipXPRegRead = 1;
498+
499+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
500+
SELECT
501+
v.*
502+
FROM (VALUES(NULL, NULL, 212)) AS v (DatabaseName, CheckID, ServerName) /*xp_regread*/
503+
WHERE @SkipXPCMDShell = 1;
504+
505+
INSERT #SkipChecks (DatabaseName, CheckID, ServerName)
506+
SELECT
507+
v.*
508+
FROM (VALUES(NULL, NULL, 2301)) AS v (DatabaseName, CheckID, ServerName) /*sp_validatelogins*/
509+
WHERE @SkipValidateLogins = 1
510+
334511
IF(OBJECT_ID('tempdb..#InvalidLogins') IS NOT NULL)
335512
BEGIN
336513
EXEC sp_executesql N'DROP TABLE #InvalidLogins;';
@@ -372,7 +549,8 @@ AS
372549
SELECT @IsWindowsOperatingSystem = 1 ;
373550
END;
374551

375-
IF NOT EXISTS ( SELECT 1
552+
553+
IF NOT EXISTS ( SELECT 1
376554
FROM #SkipChecks
377555
WHERE DatabaseName IS NULL AND CheckID = 106 )
378556
AND (select convert(int,value_in_use) from sys.configurations where name = 'default trace enabled' ) = 1
@@ -4158,53 +4336,56 @@ AS
41584336

41594337
/* First, let's check that there aren't any issues with the trace files */
41604338
BEGIN TRY
4161-
4162-
INSERT INTO #fnTraceGettable
4163-
( TextData ,
4164-
DatabaseName ,
4165-
EventClass ,
4166-
Severity ,
4167-
StartTime ,
4168-
EndTime ,
4169-
Duration ,
4170-
NTUserName ,
4171-
NTDomainName ,
4172-
HostName ,
4173-
ApplicationName ,
4174-
LoginName ,
4175-
DBUserName
4176-
)
4177-
SELECT TOP 20000
4178-
CONVERT(NVARCHAR(4000),t.TextData) ,
4179-
t.DatabaseName ,
4180-
t.EventClass ,
4181-
t.Severity ,
4182-
t.StartTime ,
4183-
t.EndTime ,
4184-
t.Duration ,
4185-
t.NTUserName ,
4186-
t.NTDomainName ,
4187-
t.HostName ,
4188-
t.ApplicationName ,
4189-
t.LoginName ,
4190-
t.DBUserName
4191-
FROM sys.fn_trace_gettable(@base_tracefilename, DEFAULT) t
4192-
WHERE
4193-
(
4194-
t.EventClass = 22
4195-
AND t.Severity >= 17
4196-
AND t.StartTime > DATEADD(dd, -30, GETDATE())
4197-
)
4198-
OR
4199-
(
4200-
t.EventClass IN (92, 93)
4201-
AND t.StartTime > DATEADD(dd, -30, GETDATE())
4202-
AND t.Duration > 15000000
4203-
)
4204-
OR
4205-
(
4206-
t.EventClass IN (94, 95, 116)
4207-
)
4339+
4340+
IF @SkipTrace = 0
4341+
BEGIN
4342+
INSERT INTO #fnTraceGettable
4343+
( TextData ,
4344+
DatabaseName ,
4345+
EventClass ,
4346+
Severity ,
4347+
StartTime ,
4348+
EndTime ,
4349+
Duration ,
4350+
NTUserName ,
4351+
NTDomainName ,
4352+
HostName ,
4353+
ApplicationName ,
4354+
LoginName ,
4355+
DBUserName
4356+
)
4357+
SELECT TOP 20000
4358+
CONVERT(NVARCHAR(4000),t.TextData) ,
4359+
t.DatabaseName ,
4360+
t.EventClass ,
4361+
t.Severity ,
4362+
t.StartTime ,
4363+
t.EndTime ,
4364+
t.Duration ,
4365+
t.NTUserName ,
4366+
t.NTDomainName ,
4367+
t.HostName ,
4368+
t.ApplicationName ,
4369+
t.LoginName ,
4370+
t.DBUserName
4371+
FROM sys.fn_trace_gettable(@base_tracefilename, DEFAULT) t
4372+
WHERE
4373+
(
4374+
t.EventClass = 22
4375+
AND t.Severity >= 17
4376+
AND t.StartTime > DATEADD(dd, -30, GETDATE())
4377+
)
4378+
OR
4379+
(
4380+
t.EventClass IN (92, 93)
4381+
AND t.StartTime > DATEADD(dd, -30, GETDATE())
4382+
AND t.Duration > 15000000
4383+
)
4384+
OR
4385+
(
4386+
t.EventClass IN (94, 95, 116)
4387+
)
4388+
END;
42084389

42094390
SET @TraceFileIssue = 0
42104391

0 commit comments

Comments
 (0)