web-dev-qa-db-fra.com

Dans quelle mesure l'octroi de l'autorisation ALTER TABLE est-il dangereux?

Imaginez le scénario suivant

CREATE DATABASE test

GO

USE test;    

CREATE TABLE dbo.Customer
  (
     CustomerId   INT,
     Email        VARCHAR(100),
     SensitiveData VARCHAR(20)
  );

INSERT INTO dbo.Customer
VALUES     (1,'[email protected]','12346789');

À un moment donné, un processus ETL est écrit qui effectue certaines activités dans la base de données test.

CREATE USER etlUser WITHOUT LOGIN; /*For demo purposes*/

CREATE TABLE dbo.StagingTable
  (
     StagingTableId INT,
     SomeData       VARCHAR(100),
  )

GRANT UPDATE,INSERT,DELETE,SELECT,ALTER ON dbo.StagingTable TO etlUser;

DENY SELECT ON dbo.Customer TO etlUser;
DENY SELECT ON dbo.Customer (SensitiveData) TO etlUser; /*For good measure*/

L'utilisateur etlUser ne doit pas avoir d'autorisations sur la table Customer (et certainement pas sur la colonne SensitiveData), donc celles-ci sont explicitement refusées ci-dessus.

Le processus ETL tronque dbo.StagingTable donc est donné ALTER les autorisations de table sur cela.

Ceci est signalé lors d'un audit de sécurité. À quel point ce scénario est-il dangereux?

11
Martin Smith

Assez dangereux ...

En plus de l'autorisation évidente de modifier la structure de StagingTable lui-même, le ALTER TABLE l'autorisation leur permet de créer des déclencheurs sur la table. Dans ce cas, grâce au chaînage de propriété, ils peuvent à la fois voir les données sensibles des clients (malgré les autorisations explicites DENY) et effectuer du vandalisme sur cette deuxième table.

EXECUTE AS user='etlUser'

GO

CREATE OR ALTER TRIGGER TR ON dbo.StagingTable AFTER UPDATE AS 
/*Exposure of sensitive data*/
SELECT * FROM dbo.Customer;

/*Vandalism*/
DELETE FROM dbo.Customer;

go

--Fire the trigger
UPDATE dbo.StagingTable SET SomeData = SomeData WHERE 1=0;

REVERT
16
Martin Smith

En plus de pouvoir ajouter des déclencheurs, l'autorisation ALTER TABLE permet également:

  1. Désactiver les déclencheurs (éviter la piste d'audit)
  2. Désactiver les contraintes (autoriser les mauvaises données)
  3. Modifier les contraintes (autoriser les mauvaises données)
  4. Modification des définitions de colonne (modification du type de données, taille maximale, NULLability)
  5. Ajouter une colonne calculée qui appelle un UDF T-SQL (ce qui rend très difficile l'obtention d'un plan parallèle, ce qui pourrait facilement nuire aux performances)

Il permet également de supprimer des colonnes, mais cela ne passera probablement pas inaperçu (car il semble que nous recherchons ici des actions potentielles plus trompeuses que malveillantes).

Heureusement, il n'est jamais nécessaire d'accorder cette autorisation à qui que ce soit, ni de l'envelopper dans une procédure stockée qui utilise le EXECUTE AS clause (généralement suivie de 'dbo' ou OWNER). Signature du module permet une abstraction facile des actions privilégiées derrière le code signé (procédures stockées, déclencheurs, UDF scalaires et TVF multi-instructions). J'ai un exemple de code montrant comment accomplir cela dans les réponses suivantes, ici sur DBA.SE:

La différence entre ces deux réponses est l'autorisation accordée à l'utilisateur basé sur la signature. L'autorisation à accorder (ou le rôle de base de données à ajouter) dépend de l'étendue de ce qui est nécessaire. Si vous n'avez besoin que d'une autorisation pour une seule table, accordez uniquement ALTER sur cette table. Si une autorisation est nécessaire pour toutes les tables d'un schéma spécifique, n'accordez pas d'autorisation à des tables individuelles, mais accordez plutôt l'autorisation au schéma lui-même. Etc.

La signature de module représente quelques étapes supplémentaires par rapport à la création d'un schéma spécifiquement pour l'utilisateur ETL ou à l'aide de EXECUTE AS clause, mais:

  1. c'est vraiment juste un simple copier-coller étant donné que le code est disponible dans les deux réponses liées ci-dessus, et
  2. c'est certainement l'option la plus sûre disponible. Il autorise uniquement cette opération via ce morceau de code, et uniquement à ceux qui ont l'autorisation EXECUTE pour ce code. Être propriétaire d'un schéma autorise certaines autorisations implicites inutiles. Et, en utilisant EXECUTE AS 'dbo' ou EXECUTE AS OWNER (en supposant que le propriétaire est dbo) donnera au processus entier , à partir de ce moment, dbo autorisations , pas seulement la procédure/déclencheur/fonction stockée que vous avez utilisée EXECUTE AS avec. La signature du module limite les autorisations uniquement au code que vous avez signé, et non à tout code appelé par le code signé.
8
Solomon Rutzky

Une meilleure pratique serait de créer un schéma de transfert, détenu par l'utilisateur ETL. Ensuite, le processus ETL peut tronquer les tables, désactiver les contraintes, effectuer une commutation de partition, etc. dans le schéma de transfert. L'utilisateur ETL n'aurait besoin que d'une autorisation limitée sur les autres schémas.

Vous pouvez également utiliser un rôle de base de données au lieu d'un seul utilisateur.

Bien sûr, vous pouvez également permettre à votre utilisateur limité d'effectuer des troncatures de table avec une procédure stockée appartenant à dbo, comme ceci:

create procedure truncate_t 
with execute as owner
as
begin
  truncate table t;
end