Empêcher SSMS de voir le système de fichiers du serveur

11

J'ai plusieurs utilisateurs qui partagent un serveur MS SQL 2017 sous mon administration. Ils ne devraient pas voir (ni même être au courant) des autres utilisateurs et de leurs données sur ce serveur. Chaque utilisateur a sa propre base de données. Ils peuvent faire tout ce qu'ils veulent avec leur base de données.

J'utilise la fonctionnalité de SQL Server Partial Containmentpour verrouiller les utilisateurs en place. Les connexions sont créées dans la base de données. Cela fonctionne bien, car ils ne voient pas d'autres comptes d'utilisateurs ou bases de données de cette façon. Les connexions DB sont ajoutées à un rôle de base de données que je crée avec cette commande:

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

Je crée un compte de connexion db et je l'ajoute uniquement audit rôle. L'utilisateur n'a aucune autre autorisation (à ma connaissance).

Le seul problème qui reste est que SSMS est toujours en mesure de parcourir le système de fichiers du serveur. Si je clique avec le bouton droit sur la base de données et que je choisis Tasks -> Restore -> Database, sélectionnez Device: -> [...]et ajoutez un fichier. Cela permet à SSMS de parcourir le système de fichiers du serveur, ce que je voudrais refuser. L'utilisateur ne peut pas réellement restaurer la base de données, mais il peut parcourir le système de fichiers.

Cette question suggère ici que SSMS utilise les procédures stockées xp_fixeddrives, xp_dirtreeet xp_fileexist. Cependant, ces procédures stockées renvoient des résultats vides lorsqu'elles sont exécutées en tant qu'utilisateur avec les autorisations dudit groupe. J'ai lu que c'est le comportement lorsqu'un utilisateur n'est pas membre du rôle sysadmin. Cela m'embrouille déjà légèrement car je refuse explicitement EXECUTE au dbrole, mais l'utilisateur peut toujours exécuter les procédures stockées. Mais quand même, lorsque vous parcourez le système de fichiers via SSMS, il n'est pas vide.

D'où SSMS obtient-il les informations sur le système de fichiers et comment puis-je éviter cela?

edit: Je viens également de remarquer que SSMS est capable de récupérer une liste de toutes les sauvegardes DB existantes sur le serveur pour toutes les bases de données. Encore une fois, je ne sais pas comment il obtient ces informations et comment je peux les empêcher.

final
la source

Réponses:

10

Traçage des requêtes

Lors du suivi des requêtes exécutées, la requête ci-dessous répertorie les dossiers sur les lecteurs un par un.

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 fonction principale utilisée est sys.dm_os_enumerate_filesystem, pour chaque dossier ouvert, elle va plus loin, un exemple de deuxième niveau:

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

Pour les connexions régulières

Pour les connexions régulières, il est aussi simple que de refuser les autorisations de sélection sur ce TVF pour empêcher l'utilisateur de répertorier les dossiers.

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

Lorsqu'il essaie de sélectionner une sauvegarde, l'utilisateur devrait voir ce message:

entrez la description de l'image ici

L'utilisateur ne pourra alors voir que les lettres de lecteur.

entrez la description de l'image ici


Pour les utilisateurs confinés

Pour l'utilisateur confiné, refuser directement la sélection sur le TVF ne fonctionne pas

L'utilisateur contenu peut exécuter avec succès l'exemple de requête suivant

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

Et .... cela ne fonctionne pas:

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

Msg 4629, niveau 16, état 10, ligne 34 Les autorisations sur les vues de catalogue étendues au serveur ou les procédures stockées système ou les procédures stockées étendues ne peuvent être accordées que lorsque la base de données actuelle est maître.

Les instructions ci-dessous fonctionnent mais ne restreignent pas l'utilisateur, même si cela ne fait pas partie du dbrolerôle

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

Qu'est-ce qui fonctionne? En théorie

Étant donné que l'utilisateur contenu utilise le compte invité / le rôle public pour se connecter et sélectionner parmi les dmv, (le rôle public a accès à certains objets par défaut), nous pourrions essayer de restreindre le rôle public.

Ce n'est pas idéal pour plusieurs raisons. Par exemple, refuser> accorder et par conséquent, seuls les membres du sysadminrôle pourront sélectionner dans ce TVF.

Une autre chose importante à noter est que la modification du rôle d'utilisateur invité / public peut avoir des effets secondaires inconnus sur l'instance ou certaines fonctionnalités.

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

La modification des autorisations publiques / invité n'est pas un scénario idéal.

Par exemple, la désactivation de l'utilisateur invité peut casser la base de données msdb .

Relancez la sélection dans le contexte de l'utilisateur contenu:

Msg 229, niveau 14, état 5, ligne 7 L'autorisation SELECT a été refusée sur l'objet 'dm_os_enumerate_filesystem', base de données 'mssqlsystemresource', schéma 'sys'.

Il peut y avoir ou non un moyen de contourner cette approche loin d'être idéale, je ne l'ai pas trouvée.

Un exemple des autorisations du rôle public:

entrez la description de l'image ici

Celles-ci sont accordées pour une raison, car de telles fonctionnalités peuvent se casser lors du refus / de la révocation de ces objets. Procéder avec prudence.

Plus d'informations sur le rôle d'utilisateur invité / public ici

Randi Vertongen
la source
1
Y a-t-il un problème à créer un nouveau rôle de maître à cette fin (par opposition au public)?
Jacob H
@JacobH Ce serait idéal, le principal problème est que l'utilisateur contenu n'a pas d'utilisateur correspondant dans master (ou une connexion sur l'instance) et par conséquent, par défaut, guest / public. Je ne pense pas qu'il soit possible de contrôler l'utilisateur lorsqu'il se connecte à master / msdb. Avertissement: Je ne suis en aucun cas un expert en bases de données contenues. Il me semble que la granularité la plus faible concerne le rôle d'utilisateur invité / public, ce qui n'est pas idéal.
Randi Vertongen
1
Pour référence, j'utilise les autorisations suivantes pour masquer les informations sur d'autres bases de données / sauvegardes / système de fichiers aux utilisateurs de bases de données contenues: 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; Jusqu'à présent, je n'ai rencontré aucun problème avec cela, mais je n'ai pas non plus effectué de tests intensifs.
final
@final Super, merci d'avoir posté une mise à jour :).
Randi Vertongen
3

Je continue de trouver plus de tables qui fuient des informations sur d'autres bases de données, j'ai donc décidé de publier cette collection de choses que je bloque pour le rôle public. Ils ne semblent affecter aucune fonctionnalité de la base de données, bien que je n'assume aucune responsabilité à ce sujet, car j'utilise uniquement un petit sous-ensemble de ce que SQL Server offre réellement. Il se pourrait très bien que cela casse quelque chose que je ne connais pas.

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
la source