私の管理下でMS SQLサーバー2017を共有するユーザーが何人かいます。彼らは、そのサーバー上の他のユーザーとそのデータを見る(または気づく)べきではありません。各ユーザーは自分のデータベースを持っています。彼らは自分のデータベースで好きなことをすることができます。
SQL ServerのPartial Containment
機能を使用して、ユーザーを適切にロックしています。ログインはデータベース内に作成されます。この方法では他のユーザーアカウントやデータベースが表示されないため、これはうまく機能します。 DBログインは、このコマンドで作成したデータベースロールに追加されます。
USE dbname
CREATE ROLE dbrole
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, CREATE VIEW, ALTER ANY SCHEMA TO dbrole
DENY EXECUTE TO dbrole
私は新たにdbログインアカウントを作成し、それを上記のロールにのみ追加します。ユーザーには他の権限はありません(私が知っていることです)。
残っている唯一の問題は、SSMSがサーバーのファイルシステムを参照できることです。データベースを右クリックしてTasks -> Restore -> Database
を選択した場合は、Device: -> [...]
を選択してファイルを追加します。これにより、SSMSがサーバーのファイルシステムを参照できるようになります。これを拒否します。ユーザーは実際にDBを復元することはできませんが、ファイルシステムを参照することはできます。
この質問はここ は、SSMSがストアドプロシージャxp_fixeddrives
、xp_dirtree
およびxp_fileexist
を使用していることを示唆しています。ただし、これらのストアドプロシージャは、そのグループの権限を持つユーザーとして実行されると、空の結果を返します。これは、ユーザーがsysadminロールのメンバーでない場合の動作であると読みました。これは、dbroleに対するEXECUTEを明示的に拒否しているため、すでに少し混乱していますが、ユーザーは引き続きストアドプロシージャを実行できます。しかし、それでも、SSMSを介してファイルシステムを参照すると、空ではありません。
SSMSはどこからファイルシステム情報を取得し、どのようにしてこれを防ぐことができますか?
編集:SSMSがすべてのデータベースのサーバーに存在するすべてのDBバックアップのリストを取得できることにも気づきました。繰り返しますが、どのようにしてこの情報を取得し、どのようにしてそれを防ぐことができますか。
実行されたクエリをトレースすると、ドライブ上のフォルダを1つずつ一覧表示する以下のクエリが見つかります。
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
、開かれたフォルダごとに、1つ下のレベルに移動し、2番目のレベルの例を示します。
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サーバースコープのカタログビュー、システムストアドプロシージャ、または拡張ストアドプロシージャのアクセス許可は、現在のデータベースがマスターである場合にのみ付与できます。
以下のステートメントは機能しますが、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から選択するため、パブリックロールはデフォルトで特定のオブジェクトにアクセスできます。パブリックロールを制限してみることができます。
これはいくつかの理由により理想的ではありません。たとえば、deny> grantとすると、sysadmin
ロールのメンバーのみがこのTVFから選択できます。
注意すべきもう1つの重要な点は、ゲストユーザー/パブリックロールを変更すると、インスタンスまたは特定の機能に未知の副作用が生じる可能性があることです。
USE MASTER
GO
DENY SELECT ON [sys].[dm_os_enumerate_filesystem] TO public;
GO
パブリック/ゲスト権限を変更することは理想的なシナリオではありません。
たとえば、ゲストユーザーを無効にすると、msdbデータベースが壊れる可能性があります 。
含まれているユーザーのコンテキストで選択を再実行します:
メッセージ229、レベル14、状態5、行7 SELECT権限は、オブジェクト「dm_os_enumerate_filesystem」、データベース「mssqlsystemresource」、スキーマ「sys」で拒否されました。
理想的なアプローチから遠く離れている方法があるかもしれないし、ないかもしれません、私はそれを見つけていません。
パブリックロールの権限の例:
これらのオブジェクトは、これらのオブジェクトを拒否または取り消すと機能しなくなる可能性があるため、許可されています。注意して続行してください。
ゲストユーザー/パブリックロールに関するいくつかの詳細 ここ
私は他のデータベースに関する情報を漏らすテーブルをさらに見つけ続けているので、私がブロックするもののこのコレクションをパブリックロールに投稿することにしました。 SQL Serverが実際に提供するものの小さなサブセットのみを使用しているので、それらはdbの機能に影響を与えていないようですが、私はその責任を負いません。これは、私が知らない何かを壊すことになるでしょう。
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