SQL: Uprawnienie db_owner bez usuwania bazy danych

9-sie-2019

Sam nie wiem z czego to wynika, ale uzytkownicy proponuja czasami nieco abstrakcyjne rozwiazania zwiazane z ustawieniem uprawnien do bazy danych.

W tym przypadku klient chcial aby uzytkownicy bazy danych mogli pracowac na poziomie uprawnien db_owner, ale z jednym malym haczykiem. Uzytkownicy nie powinni moc usunac bazy danych. Dlaczego uwazam, ze zyczenie jest nieco abstrakcyjne? Otoz db_owner to bardzo wysokie uprawnienie, wiec zlosliwy uzytkownik moze:

  • pousuwac tabele
  • zmodyfikowac procedury
  • zabrac uprawnienia innym uzytkownikom
  • itp.

Wydaje sie ze lepszym rozwiazaniem byloby wybranie tylko tych uprawnien, ktore sa rzeczywiscie potrzebne i nadanie ich do roli bazy danych. Potem uzytkownikow wystarczy przypisywac do tej roli. Byloby bezpieczniej.

No ale… usuniecie bazy danych jak opisano w https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-transact-sql?view=sql-server-2017 moze byc wykonane tylko w 3 przypadkach:

  • uzytkownik ma upranienie ALTER ANY DATABASE
  • uzytkownik ma uprawnienie CONTROL
  • uzytkownik jest db_ownerem

Requires the CONTROL permission on the database, or ALTER ANY DATABASE permission, or membership in the db_owner fixed database role.

Skoro u nas uzytkownik jest db_ownerem, to mozna mu zabrac uprawnienie do kasowania bazy tylko na 2 sposoby:

  • deny alter any database to user_name
  • deny control on database::db_name to user_name

Pierwsza z tych metod powoduje, ze uzytkownik nie moze np tworzyc tabel w bazie danych, dodawac nowych uzytkownikow, wiec generalnie do niczego taki db_owner sie nie nadaje

Druga z tych metod uniemozliwia korzystanie z bazy danych, wiec ogolnie odpowiedz na pytanie czy taka konfiguracje mozna stworzyc brzmi „nie”.

Jest jednak szansa na zbudowanie obejscia tego problemu. Od czego mamy DDL trigger na poziomie serwera?

Mozna stworzyc nowa role na serwerze np. deny_drop i przypisac do niej uzytkownikow, ktorzy maja miec zakaz usuwania baz danych:

USE [master]
GO
CREATE SERVER ROLE [deny_drop]
GO
ALTER SERVER ROLE [deny_drop] ADD MEMBER [user_name]
GO

Nastepnie mozna stworzyc DDL trigger, ktory jesli zauwazy, ze kasowanie bazy danych jest wykonywane przez uzytkownika nalezacego do danej roli, to wykona rollback:

CREATE TRIGGER DenyDatabaseDrop ON ALL SERVER FOR DROP_DATABASE
AS

DECLARE @db_name SYSNAME, @event_data XML
SET @event_data = EVENTDATA()
SELECT @db_name=@event_data.value('data(/EVENT_INSTANCE/DatabaseName)[1]', 'SYSNAME')

IF @db_name IN ('restricted_database_name') AND (IS_SRVROLEMEMBER('deny_drop') = 1)
BEGIN
 PRINT 'To drop this database contact your DBA'
 ROLLBACK;
END
GO

ENABLE TRIGGER [DenyDatabaseDrop] ON ALL SERVER

No i w sumie gotowe. Jesli uzytkownik jest w roli deny_drop i usunie baze , ktorej nazwa jest podana w wyrazeniu IF powyzej, to wykona sie rollback i baza nie bedzie usunieta.

Oczywiscie to jest obejscie problemu. Nie jest to czysty srodek security. Popranie, nadajac uprawnienia nalezy to zrobic z glowa!

 

Komentarze są wyłączone

Autor: Rafał Kraik