Impedir que o SSMS veja o sistema de arquivos do servidor

11

Tenho vários usuários que compartilham um servidor MS SQL 2017 sob minha administração. Eles não devem ver (ou mesmo estar cientes) dos outros usuários e seus dados nesse servidor. Cada usuário tem seu próprio banco de dados. Eles podem fazer o que quiserem com o banco de dados.

Estou usando o Partial Containmentrecurso do SQL Server para bloquear os usuários no lugar. Os logins são criados dentro do banco de dados. Isso funciona bem, pois eles não veem outras contas de usuário ou bancos de dados dessa maneira. Os logins do banco de dados são adicionados a uma função de banco de dados que eu crio com este comando:

USE dbname
CREATE ROLE dbrole
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, CREATE VIEW, ALTER ANY SCHEMA TO dbrole
DENY EXECUTE TO dbrole

Recentemente, crio uma conta de login no banco de dados e a adiciono apenas à referida função. O usuário não tem outras permissões (que eu saiba).

O único problema que resta é que o SSMS ainda é capaz de navegar no sistema de arquivos do servidor. Se clicar com o botão direito do mouse no banco de dados e escolher Tasks -> Restore -> Database, selecione Device: -> [...]e adicione um arquivo. Isso permite que o SSMS navegue no sistema de arquivos do servidor, o que eu gostaria de negar. O usuário não pode realmente restaurar o banco de dados, mas ele pode navegar no sistema de arquivos.

Esta questão aqui sugere que SSMS está usando os procedimentos armazenados xp_fixeddrives, xp_dirtreee xp_fileexist. No entanto, esses procedimentos armazenados retornam resultados vazios quando executados como um usuário com as permissões do referido grupo. Eu li que esse é o comportamento quando um usuário não é membro da função sysadmin. Isso já me confunde um pouco, pois nego explicitamente EXECUTE ao dbrole, mas o usuário ainda pode executar os procedimentos armazenados. Mas ainda assim, ao navegar no sistema de arquivos pelo SSMS, ele não está vazio.

De onde o SSMS obtém as informações do sistema de arquivos e como posso evitar isso?

edit: Acabei de notar que o SSMS é capaz de recuperar uma lista de todos os backups de banco de dados existentes no servidor para todos os bancos de dados. Novamente, não sei como obtém essas informações e como posso evitá-las.

final
fonte

Respostas:

10

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:

insira a descrição da imagem aqui

O usuário poderá ver apenas as letras da unidade.

insira a descrição da imagem aqui


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 dbrolefunçã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 sysadminfunçã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:

insira a descrição da imagem aqui

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

Randi Vertongen
fonte
11
Existe alguma dificuldade em criar um novo papel no mestre para esse fim (em oposição ao público)?
Jacob H
@JacobH Isso seria ideal, o principal problema é que o usuário contido não possui um usuário correspondente no mestre (ou um login na instância) e, como resultado, o padrão é convidado / público. Eu não acho que é possível controlar o usuário como ele se conecta ao master / msdb. Isenção de responsabilidade: Eu não sou, de forma alguma, um especialista em banco de dados. Parece-me que a granularidade mais baixa está na função pública / usuário convidado, o que não é o ideal.
Randi Vertongen
11
Para referência, estou usando as seguintes permissões para ocultar informações sobre outros bancos de dados / backups / sistema de arquivos de usuários de banco de dados contidos: USE MASTER; DENY SELECT ON [sys].[dm_os_enumerate_fixed_drives] TO public; DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO public; USE msdb; DENY SELECT ON msdb.dbo.backupset TO public; Até agora, não encontrei problemas com isso, mas também não fiz testes intensivos.
final de
@ final Ótimo, obrigado por postar uma atualização :).
Randi Vertongen
3

Eu continuo encontrando mais tabelas que vazam informações sobre outros bancos de dados e, por isso, decidi postar essa coleção de coisas que bloqueio para a função pública. Eles não parecem afetar nenhuma funcionalidade de banco de dados, embora eu não assuma nenhuma responsabilidade, pois estou usando apenas um pequeno subconjunto do que o SQL Server realmente oferece. Pode muito bem ser que isso quebre algo que eu desconheço.

USE MASTER
GO
DENY SELECT ON [sys].[dm_os_enumerate_fixed_drives] TO public
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO public
GO
USE msdb
GO
DENY SELECT ON msdb.dbo.backupfile TO public
DENY SELECT ON msdb.dbo.backupfilegroup TO public
DENY SELECT ON msdb.dbo.backupmediafamily TO public
DENY SELECT ON msdb.dbo.backupmediaset TO public
DENY SELECT ON msdb.dbo.restorefile TO public
DENY SELECT ON msdb.dbo.restorefilegroup TO public
DENY SELECT ON msdb.dbo.restorehistory TO public
GO
final
fonte