Evitar que SSMS vea el sistema de archivos del servidor

11

Tengo varios usuarios que comparten un servidor MS SQL 2017 bajo mi administración. No deberían ver (ni siquiera estar al tanto) de los otros usuarios y sus datos en ese servidor. Cada usuario tiene su propia base de datos. Pueden hacer lo que quieran con su base de datos.

Estoy usando la Partial Containmentfunción de SQL Server para bloquear a los usuarios en su lugar. Los inicios de sesión se crean dentro de la base de datos. Esto funciona bien, ya que no ven otras cuentas de usuario o bases de datos de esta manera. Los inicios de sesión de la base de datos se agregan a un rol de base de datos que creo con 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

Recién creo una cuenta de inicio de sesión de db y solo la agrego a dicho rol. El usuario no tiene otros permisos (que yo sepa).

El único problema que queda es que SSMS aún puede explorar el sistema de archivos del servidor. Si hago clic derecho en la base de datos y elijo Tasks -> Restore -> Database, luego selecciono Device: -> [...]y agrego un archivo. Esto permite que SSMS explore el sistema de archivos del servidor, lo que me gustaría negar. El usuario no puede restaurar la base de datos, pero puede navegar por el sistema de archivos.

Esta pregunta aquí sugiere que SSMS está utilizando los procedimientos almacenados xp_fixeddrives, xp_dirtreey xp_fileexist. Sin embargo, esos procedimientos almacenados devuelven resultados vacíos cuando se ejecutan como un usuario con los permisos de dicho grupo. He leído que este es el comportamiento cuando un usuario no es miembro de la función sysadmin. Esto ya me confunde un poco ya que niego explícitamente EXECUTE al dbrole, pero el usuario aún puede ejecutar los procedimientos almacenados. Pero aún así, cuando navega por el sistema de archivos a través de SSMS, no está vacío.

¿De dónde obtiene SSMS la información del sistema de archivos y cómo puedo evitar esto?

editar: también me di cuenta de que SSMS puede recuperar una lista de todas las copias de seguridad de bases de datos existentes en el servidor para todas las bases de datos. Nuevamente, no sé cómo obtiene esta información y cómo puedo evitarla.

final
fuente

Respuestas:

10

Rastreando las consultas

Al rastrear las consultas ejecutadas, a continuación se encuentra la consulta que enumera las carpetas en las unidades una por una.

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

La función principal utilizada es sys.dm_os_enumerate_filesystem, para cada carpeta que se abre, va un nivel más profundo, un ejemplo de un segundo nivel:

select @Path = N'D:\Data\'

Para inicios de sesión regulares

Para los inicios de sesión regulares, es tan fácil como negar los permisos seleccionados en este TVF para que el usuario no pueda enumerar las carpetas.

DENY SELECT ON master.sys.dm_os_enumerate_filesystem TO [Domain\LoginName]

Al intentar seleccionar una copia de seguridad, el usuario debería ver este mensaje:

ingrese la descripción de la imagen aquí

El usuario solo podrá ver las letras de unidad.

ingrese la descripción de la imagen aquí


Para usuarios contenidos

Para el usuario contenido, negar la selección en el TVF directamente no funciona

El usuario contenido puede ejecutar con éxito el siguiente ejemplo 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

Y ... esto no funciona:

use [PartialDb]
GO
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO [PartialUser];
GO

Msg 4629, Nivel 16, Estado 10, Línea 34 Los permisos en vistas de catálogo con ámbito de servidor o procedimientos almacenados del sistema o procedimientos almacenados extendidos solo se pueden otorgar cuando la base de datos actual es maestra.

Las siguientes declaraciones funcionan pero no restringen al usuario, incluso si no es parte del dbrolerol

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];

Que funciona En teoria

Dado que el usuario contenido utiliza la cuenta de invitado / rol público para conectarse y seleccionar de dmv (el rol público tiene acceso a ciertos objetos por defecto), podríamos intentar restringir el rol público.

Esto no es ideal debido a una serie de razones. Por ejemplo, denegar> otorgar y, como resultado, solo los miembros en el sysadminrol podrán seleccionar de este TVF.

Otra cosa importante a tener en cuenta es que cambiar el rol de usuario invitado / público puede tener efectos secundarios desconocidos en la instancia o ciertas funcionalidades.

USE MASTER
GO
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO public;
GO

Cambiar los permisos públicos / invitados no es un escenario ideal.

Por ejemplo, deshabilitar el usuario invitado puede romper la base de datos msdb .

Volver a ejecutar la selección en el contexto del usuario contenido:

Mensaje 229, Nivel 14, Estado 5, Línea 7 El permiso SELECT fue denegado en el objeto 'dm_os_enumerate_filesystem', base de datos 'mssqlsystemresource', esquema 'sys'.

Puede haber o no una forma de evitar este enfoque lejos de ser ideal, no lo he encontrado.

Un ejemplo de los permisos del rol público:

ingrese la descripción de la imagen aquí

Estos se otorgan por una razón, ya que ciertas funcionalidades pueden romperse al negar / revocar estos objetos. Proceda con precaución.

Más información sobre el usuario invitado / rol público aquí

Randi Vertongen
fuente
1
¿Hay algún problema para crear un nuevo rol en maestro para este propósito (en oposición al público)?
Jacob H
@JacobH Eso sería ideal, el problema principal es que el usuario contenido no tiene un usuario correspondiente en el maestro (o un inicio de sesión en la instancia) y, como resultado, el valor predeterminado es invitado / público. No creo que sea posible controlar al usuario mientras se conecta a master / msdb. descargo de responsabilidad: de ninguna manera soy un experto en bases de datos. Me parece que la granularidad más baja está en el rol de usuario invitado / público, lo que no es ideal.
Randi Vertongen
1
Como referencia, estoy usando los siguientes permisos para ocultar información sobre otras bases de datos / Copias de seguridad / Sistema de archivos de los usuarios de la base de datos: 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; Hasta ahora, no he encontrado problemas con esto, pero tampoco he realizado pruebas intensivas.
final
@final Genial, gracias por publicar una actualización :).
Randi Vertongen
3

Sigo encontrando más tablas que filtran información sobre otras bases de datos, por lo tanto, decidí publicar esta colección de cosas que bloqueo para el rol público. No parecen afectar ninguna funcionalidad de db, aunque no me hago responsable de eso, ya que solo estoy usando un pequeño subconjunto de lo que SQL Server realmente ofrece. Bien podría ser que esto rompa algo de lo que no soy consciente.

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
fuente