追踪查询
跟踪执行的查询时,将在下面的查询中逐一列出驱动器上的文件夹。
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权限被拒绝。
解决理想方法的方法可能有也可能没有,我还没有找到。
公共角色权限的示例:
授予这些权限是有原因的,因为在拒绝/撤消这些对象时,某些功能可能会中断。请谨慎操作。
有关来宾用户/公共角色的更多信息,请点击此处