Refuser l'accès au schéma d'informations dans SQL Server

13

Je recherche le meilleur moyen de désactiver l'accès au sys.tables/ Information Schemapour un utilisateur / groupe dans SQL Server.

J'ai trouvé ce fil de 2008

Il montre comment refuser l'accès [sys].[something]comme ceci:

 DENY SELECT ON [sys].[columns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[tables] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[syscolumns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[sysobjects] TO DenySystemTableSelectRole
 GO

Mais aucun moyen de désactiver l'accès sur Information Schema:

DENY SELECT ON INFORMATION_SCHEMA.TABLES To DenySystemTableSelectRole

Cela ne semble pas fonctionner.

Comment puis-je désactiver l'accès à information_schema?

Et existe-t-il un moyen plus simple de désactiver l'accès à tous sys/ information_schema?

Mise à jour: En fait, je ne peux pas exécuter les deux déclarations suivantes:

DENY SELECT ON [sys] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA To reducedDBO
GO

J'ai essayé de les exécuter sur la base de données spécifique où l'utilisateur existe, et j'ai également essayé sur le "maître".

Je peux toujours courir:

 SELECT * from
 INFORMATION_SCHEMA.TABLES 

-> renvoie toujours les résultats

 SELECT * from
 sys.TABLES 

-> plus de résultats

L'inclusion SCHEMA::dans la requête a permis de créer les sécurisables

DENY SELECT ON SCHEMA::[sys] TO reducedDBO
GO
DENY SELECT ON SCHEMA::INFORMATION_SCHEMA To reducedDBO
GO

Mais maintenant, je peux toujours sélectionner toutes les informations de la base de données.

J'ai jeté un œil à l'onglet "Securables" dans la fenêtre de propriétés des utilisateurs dans Management Studio 2008, il ressemble à ceci:

Entrée qui bloque la sélection de sys.tables

Schéma: sys, Nom: tables, Type: Affichage

Autorisations pour sys.tables: Autorisation: sélectionner, concédant: dbo, refuser est coché

Entrée qui ne bloque aucune sélection

Schéma:, Nom: INFORMATION_SCHEMA, Type: Schéma

Autorisations pour INFORMATION_SCHEMA: Autorisation: sélectionner, concédant: dbo, le refus n'est PAS vérifié (j'ai essayé de le vérifier, mais aucune chance ..)

Autorisation: Sélectionnez, Grantor: INFORMATION_SCHEMA, Refuser est vérifié


J'ai essayé de définir les autorisations sur l'interface graphique, mais je reçois la même erreur que la définition des autorisations ne serait possible que sur la base de données principale. Mais je n'ai pas l'utilisateur / login ajouté à la sécurité des DB maîtres.

Solution:

La seule façon dont je pouvais faire le denytravail pour le information_schemaétait d' ajouter l'utilisateur au master-db et d'exécuter le deny selectsur le master:

DENY SELECT ON [sys].[tables] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA.TABLES To reducedDBO
GO

Et comme dans ce code, il ne peut être exécuté que pour des tables uniques.

SwissCoder
la source
1
Consultez également cette question dba.se et sa réponse par Remus Rusanu - couvre en quelque sorte le même sujet
marc_s
Oui merci. En fait, la différence entre refuser les vues [information_schema] et les vues [sys] est que le [information_schema] doit être désactivé sur le maître (et cela affectera toutes les bases de données) tandis que la vue [sys] doit être désactivée sur chaque base de données elle-même, et même si elle est désactivée sur le maître, l'utilisateur pourra toujours sélectionner dans la vue, si elle n'est pas également désactivée sur la base de données actuelle.
SwissCoder

Réponses:

10

Vous devriez être en mesure de simplement refuser les autorisations sur l'ensemble syset le information_schemaschéma dans son ensemble:

DENY SELECT On SCHEMA::sys To [user_name]
DENY SELECT On SCHEMA::INFORMATION_SCHEMA To [user_name]

Cela devrait simplement empêcher cet utilisateur de faire des sélections dans ces deux schémas.

marc_s
la source
marqué comme réponse, mais le problème est que SCHEMA :: n'a pas aidé, mieux vaut le supprimer à nouveau. La solution consiste à ajouter l'utilisateur à la base de données maître, puis à exécuter le script de refus sur le maître. Merci de votre aide!
SwissCoder
Oh et en fait, je ne peux pas non plus désactiver l'intégralité du SCHEMA, seul l'accès aux tables individuelles peut être désactivé comme ceci.
SwissCoder
5

Premièrement, vous avez raison en ce que la façon (légèrement contre-intuitive) d'empêcher l'accès aux schémas [sys] et [INFORMATION_SCHEMA] consiste à s'assurer d'abord que la connexion (enfin, principal au niveau du serveur) existe en tant qu'utilisateur (erm, principal au niveau de la base de données) dans la base de données master.

Supposons que vous ayez une connexion SQL pour plus de simplicité:

CREATE LOGIN [testy] WITH PASSWORD=N'SCoBIqlJELGzrY9zYsKWC5z3kHtMsyCAP6yBHLUYQ0w='
go

Créez maintenant un utilisateur correspondant dans la base de données master:

use [master]
go
CREATE USER [testy] FOR LOGIN [testy]
go

Vous voulez maintenant empêcher cette connexion d'accéder à l'une des tables des schémas fournis par le système - [sys] et [INFORMATION_SCHEMA].

Il semble qu'il y ait eu un changement de comportement entre SQL Server 2008 R2 et SQL Server 2012:

Dans SQL Server 2012 (et probablement dans les versions ultérieures), l'exécution de ce qui suit dans la base de données [master] fait ce que vous attendez:

DENY SELECT, VIEW DEFINITION ON SCHEMA::[sys] to [testy];
GO
DENY SELECT, VIEW DEFINITION ON SCHEMA::[INFORMATION_SCHEMA] to [testy];
GO

Cependant, dans SQL Server 2008 R2 (et probablement dans les versions antérieures), les déclarations d'octroi de stock donnant accès aux objets de ces schémas aux membres de [public] semblent remplacer les instructions DENY ci-dessus, ce qui me semble être une énorme pile d'échecs. Par conséquent, sur 2008 R2, vous devez explicitement refuser chaque subvention à [public]. Voici un script pour le faire:

declare
    @database_principal sysname,
    @cur cursor,
    @sql nvarchar( 4000 );

set @database_principal = 'testy';

set @cur = cursor local forward_only static for
    select 
        'DENY ' +
        permission_name + ' on ' +
        case class 
            when 1 then
                case minor_id
                    when 0 then 'OBJECT'
                    else 'COLUMN'
                end
            else
                class_desc
        end + '::' +
        case class
            when 0 then db_name()
            when 1 then quotename( OBJECT_SCHEMA_NAME(major_id) ) + '.' + quotename( object_name( major_id ) ) + case minor_id when 0 then '' else ( select '.' + quotename( name ) collate database_default from sys.columns where column_id=minor_id) end
            when 3 then schema_name( major_id )
        end + ' to ' +
        quotename( @database_principal )
    from
        sys.database_permissions
    where
        [grantee_principal_id] = 0 -- public
        and
        [state_desc] = 'GRANT'
        and
        [permission_name] = 'SELECT'
;

open @cur;

while
    1 = 1
begin
    fetch @cur into @sql;
    if @@fetch_status <> 0 break;

    print @sql;
    exec sys.sp_executesql @sql;
end;

close @cur;

deallocate @cur;

Exécutez ce qui précède dans la base de données master et vous avez supprimé l'accès au contenu de ces schémas.

Remarques:

  1. Étant donné qu'il s'agit d'instructions DENY explicites, elles sont correctes au moment où le script est exécuté. Si quelqu'un modifie par la suite les autorisations accordées au public (par exemple, un Service Pack crée une nouvelle table système), cela sera exposé à l'utilisateur refusé.
  2. C'est une bonne idée d'utiliser un rôle de base de données comme cible des instructions DENY et de placer les utilisateurs refusés dans ce rôle.
  3. Vous pouvez annuler cela en changeant le DENY en REVOKE
  4. Si vous commentez les deux lignes suivantes dans le script ci-dessus:

        and
        [permission_name] = 'SELECT'

    Cela aura pour effet d'annuler TOUS les GRANT par défaut pour le public. Cela empêchera par exemple l'accès à sys.sp_tables et donc la capacité de Microsoft Access par exemple à énumérer les tables, mais il est utile dans les scénarios de haute sécurité de le faire pour que les utilisateurs n'obtiennent l'accès que là où vous l'avez explicitement accordé. il.

Alasdair CS
la source
3

Je ne sais pas quand cette astuce est devenue disponible - puisque personne ne l'a mentionné - mais il semble qu'elle fonctionne au moins depuis SQL Server 2008.

DENY VIEW DEFINITION to [database-role / database-user];

Ce qui précède fonctionne sans avoir à ajouter l'utilisateur à la masterbase de données comme mentionné dans certaines des autres réponses.

Jesse
la source
Excellente réponse! Per technet.microsoft.com/en-us/library/ms175808(v=sql.105).aspx "annule l'accès aux métadonnées basé sur les autorisations pour le bénéficiaire dans la base de données spécifiée"
Chris Anton