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:
El usuario solo podrá ver las letras de unidad.
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 dbrole
rol
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 sysadmin
rol 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:
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í