Rastreando as consultas
Ao rastrear as consultas executadas, é encontrada a consulta abaixo, que lista as pastas nas unidades, uma por uma.
declare @Path nvarchar(255)
declare @Name nvarchar(255)
select @Path = N'D:\'
select @Name = null;
create table #filetmpfin (Name nvarchar(255) NOT NULL, IsFile bit NULL, FullName nvarchar(300) not NULL)
declare @FullName nvarchar(300)
if exists (select 1 from sys.all_objects where name = 'dm_os_enumerate_filesystem' and type = 'IF' and is_ms_shipped = 1)
begin
if (@Name is null)
begin
insert #filetmpfin select file_or_directory_name, 1 - is_directory, full_filesystem_path from sys.dm_os_enumerate_filesystem(@Path, '*') where [level] = 0
end
if (NOT @Name is null)
begin
if(@Path is null)
select @FullName = @Name
else
select @FullName = @Path + convert(nvarchar(1), serverproperty('PathSeparator')) + @Name
create table #filetmp3 ( Exist bit NOT NULL, IsDir bit NOT NULL, DirExist bit NULL )
insert #filetmp3 select file_exists, file_is_a_directory, parent_directory_exists from sys.dm_os_file_exists(@FullName)
insert #filetmpfin select @Name, 1-IsDir, @FullName from #filetmp3 where Exist = 1 or IsDir = 1
drop table #filetmp3
end
end
else
begin
if(@Name is null)
begin
if (right(@Path, 1) = '\')
select @Path= substring(@Path, 1, len(@Path) - charindex('\', reverse(@Path)))
create table #filetmp (Name nvarchar(255) NOT NULL, depth int NOT NULL, IsFile bit NULL )
insert #filetmp EXECUTE master.dbo.xp_dirtree @Path, 1, 1
insert #filetmpfin select Name, IsFile, @Path + '\' + Name from #filetmp f
drop table #filetmp
end
if(NOT @Name is null)
begin
if(@Path is null)
select @FullName = @Name
else
select @FullName = @Path + '\' + @Name
if (right(@FullName, 1) = '\')
select @Path= substring(@Path, 1, len(@FullName) - charindex('\', reverse(@FullName)))
create table #filetmp2 ( Exist bit NOT NULL, IsDir bit NOT NULL, DirExist bit NULL )
insert #filetmp2 EXECUTE master.dbo.xp_fileexist @FullName
insert #filetmpfin select @Name, 1-IsDir, @FullName from #filetmp2 where Exist = 1 or IsDir = 1
drop table #filetmp2
end
end
SELECT
Name AS [Name],
IsFile AS [IsFile],
FullName AS [FullName]
FROM
#filetmpfin
ORDER BY
[IsFile] ASC,[Name] ASC
drop table #filetmpfin
A principal função usada é sys.dm_os_enumerate_filesystem
, para cada pasta que é aberta, vai um nível mais profundo, um exemplo de um segundo nível:
select @Path = N'D:\Data\'
Para logins regulares
Para logins regulares, é tão fácil quanto negar as permissões de seleção neste TVF para tornar o usuário incapaz de listar as pastas.
DENY SELECT ON master.sys.dm_os_enumerate_filesystem TO [Domain\LoginName]
Ao tentar selecionar um backup, o usuário deve ver esta mensagem:
O usuário poderá ver apenas as letras da unidade.
Para usuários contidos
Para o usuário contido, negar a seleção diretamente no TVF não funciona
O usuário contido pode executar com êxito o próximo exemplo de consulta
declare @Path nvarchar(255)
declare @Name nvarchar(255)
select @Path = N'D:\'
select file_or_directory_name, 1 - is_directory, full_filesystem_path from sys.dm_os_enumerate_filesystem(@Path, '*') where [level] = 0
E .... isso não funciona:
use [PartialDb]
GO
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO [PartialUser];
GO
Mensagem 4629, nível 16, estado 10, linha 34 As permissões nas exibições de catálogo com escopo no servidor ou nos procedimentos armazenados do sistema ou nos procedimentos armazenados estendidos podem ser concedidas somente quando o banco de dados atual é mestre.
As instruções abaixo funcionam, mas não restringem o usuário, mesmo que não faça parte da dbrole
função
DENY VIEW DATABASE STATE TO [PartialUser];
DENY VIEW DEFINITION ON SCHEMA :: information_schema TO [PartialUser];
DENY VIEW DEFINITION ON SCHEMA :: sys TO [PartialUser];
DENY SELECT ON SCHEMA :: information_schema TO [PartialUser];
DENY SELECT ON SCHEMA :: sys TO [PartialUser];
O que funciona? Em teoria
Como o usuário contido usa a conta de convidado / função pública para conectar-se e selecionar entre os dmv (a função pública tem acesso a determinados objetos por padrão), podemos tentar restringir a função pública.
Isso não é o ideal devido a várias razões. Por exemplo, negar> conceder e, como resultado, apenas os membros da sysadmin
função poderão selecionar esse TVF.
Outro ponto importante a ser observado é que a alteração da função pública / usuário convidado pode ter efeitos colaterais desconhecidos na instância ou em determinadas funcionalidades.
USE MASTER
GO
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO public;
GO
Alterar permissões de público / convidado não é um cenário ideal.
Por exemplo, desabilitar o usuário convidado pode interromper o banco de dados msdb .
Execute novamente a seleção no contexto do usuário contido:
Msg 229, Nível 14, Estado 5, Linha 7 A permissão SELECT foi negada no objeto 'dm_os_enumerate_filesystem', banco de dados 'mssqlsystemresource', esquema 'sys'.
Pode ou não haver uma maneira de contornar isso longe da abordagem ideal, eu não a encontrei.
Um exemplo das permissões da função pública:
Eles são concedidos por um motivo, pois certas funcionalidades podem se quebrar ao negar / revogar esses objetos. Prossiga com cuidado.
Mais algumas informações sobre o usuário convidado / função pública aqui