防止SSMS查看服务器的文件系统


11

我有几个用户在我的管理下共享MS SQL Server 2017。他们不应该看到(甚至不知道)该服务器上的其他用户及其数据。每个用户都有自己的数据库。他们可以使用他们的数据库做任何想要的事情。

我正在使用SQL Server的Partial Containment功能将用户锁定在适当的位置。登录名是在数据库内部创建的。这样效果很好,因为他们看不到其他用户帐户或数据库。将数据库登录名添加到我使用以下命令创建的数据库角色中:

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

我刚刚创建了一个数据库登录帐户,仅将其添加到上述角色。用户没有其他权限(据我所知)。

剩下的唯一问题是SSMS仍然能够浏览服务器的文件系统。如果我右键单击数据库并选择Tasks -> Restore -> Database,然后选择Device: -> [...]并添加文件。这使SSMS可以浏览服务器的文件系统,我想否认这一点。用户实际上不能还原数据库,但可以浏览文件系统。

这里的问题表明SSMS正在使用存储过程xp_fixeddrivesxp_dirtree并且xp_fileexist。但是,这些存储过程在具有所述组许可的用户身份执行时返回空结果。我已经读到,这是用户不是sysadmin角色成员时的行为。这已经使我有些困惑,因为我明确拒绝了执行该命令,但是用户仍然可以执行存储过程。但是,当通过SSMS浏览文件系统时,它不是空的。

SSMS从哪里获取文件系统信息,如何防止这种情况发生?

编辑:我也刚刚注意到,SSMS能够检索所有数据库在服务器上存在的所有数据库备份的列表。再说一次,我不知道它如何获得这些信息以及如何防止它。

Answers:


10

追踪查询

跟踪执行的查询时,将在下面的查询中逐一列出驱动器上的文件夹。

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

所使用的主要功能是sys.dm_os_enumerate_filesystem,对于每个打开的文件夹,它会更深入一层,例如第二层:

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

对于常规登录

对于常规登录,就像拒绝该TVF的选择权限一样简单,以使用户无法列出文件夹。

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

尝试选择备份时,用户应看到以下消息:

在此处输入图片说明

然后,用户将只能看到驱动器号。

在此处输入图片说明


对于包含的用户

对于包含的用户,直接在TVF上拒绝选择不起作用

包含的用户可以成功运行下一个查询示例

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

而且....这不起作用:

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

消息4629,级别16,状态10,第34行仅在当前数据库为master时,才能授予服务器范围的目录视图或系统存储过程或扩展存储过程的权限。

下面的语句有效,但是它们不限制用户,即使它不是dbrole角色的一部分

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

有什么用? 理论上

由于包含的用户使用来宾帐户/公共角色连接并从dmv中选择(默认情况下,公共角色有权访问某些对象),因此我们可以尝试限制公共角色。

由于多种原因,这是不理想的。例如,拒绝>授予,因此只有sysadmin角色中的成员才能从该TVF中进行选择。

还要注意的另一件事是,更改来宾用户/公共角色可能会对实例或某些功能产生未知的副作用。

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

更改公共/来宾权限不是理想的方案。

例如,禁用来宾用户可以破坏msdb数据库

在包含的用户的上下文中重新运行选择:

消息229,级别14,状态5,第7行,对对象'dm_os_enumerate_filesystem',数据库'mssqlsystemresource',架构'sys'的SELECT权限被拒绝。

解决理想方法的方法可能有也可能没有,我还没有找到。

公共角色权限的示例:

在此处输入图片说明

授予这些权限是有原因的,因为在拒绝/撤消这些对象时,某些功能可能会中断。请谨慎操作。

有关来宾用户/公共角色的更多信息,请点击此处


1
为此目的(相对于公众而言)是否有必要在大师中创建新角色?
Jacob H

@JacobH这将是理想的,主要问题是所包含的用户在master(或实例的登录名)中没有相应的用户,因此默认为guest / public。我认为在连接到master / msdb时无法控制用户。免责声明:我绝对不是数据库专家。 在我看来,最低粒度取决于来宾用户/公共角色,这不是理想的选择。
兰迪·沃顿根

1
作为参考,我正在使用以下权限向包含的数据库用户隐藏有关其他DB /备份/文件系统的信息: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; 到目前为止,我还没有遇到任何问题,但是我也没有进行深入的测试。
最后

@final很好,感谢您发布更新:)。
兰迪·沃顿根

3

我一直在寻找更多泄漏其他数据库信息的表,因此我决定将这些阻止我担任公共角色的事情收集起来。它们似乎不影响任何数据库功能,尽管我对此不承担任何责任,因为我只使用了SQL Server实际提供的一小部分。很有可能这会破坏我不知道的东西。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.