Sicherheit: Delegation of Authority

(Teil 3 meiner Artikelserie über Sicherheitsprinzipien in Microsoft SQL-Servern & Datenbanken)

Um es gleich vorwegzunehmen: Delegation (Delegierung) ist eher ein Prozess oder ein Konzept als ein Prinzip. Aber es ist eine besonders nützliche Praxis, die man im Auge behalten sollte, wenn man ein Sicherheitskonzept entwirft, und sie steht in engem Zusammenhang mit den besprochenen Sicherheitsprinzipien wie dem Prinzip des geringsten Privilegs und der Aufgabentrennung, wie Sie noch herausfinden werden.

Also, worum geht es? Delegation (of Authority) ist der Prozess, bestimmte Berechtigungen an andere Benutzer weiterzugeben, oft vorübergehend, ohne deren Gesamtprivilegien auf die gleiche Stufe zu heben wie die des delegierenden Accounts/Users.

Es gibt zwei leicht unterschiedliche Ansätze. Die Delegation kann entweder…

1) auf der Identitätsebene geschehen: indem erlaubt wird, dass die Identität A von der Identität B genutzt werden kann. Beispiele in Betriebssystemen sind die „Runas“- und „sudo“-Befehle in Windows, bzw. Unix/Linux.

Oder

2) es kann auf der Ebene der Autorisierung geschehen: im Wesentlichen durch die Weitergabe eines festgelegten Satzes von Berechtigungen über eine Form der rollenbasierten Zugriffskontrolle (RBAC*) an eine andere Identität.

Wer sich zweistufige Anwendungsarchitekturen und die Authentifizierungsabläufe ansieht, wird wahrscheinlich feststellen, dass die Delegation ein recht häufiges Muster ist.

OAuth und On-behalf-of-Token zur Authentifizierung

OAuth ist zum Beispiel ein offener Standard für die Zugriffsdelegation, der auch in Azure Active Directory (AAD) verwendet wird. Mithilfe des OAuth 2.0 On-Behalf-Of-flows (OBO) können Anwendungen eine Dienst-API aufrufen, die wiederum eine andere Dienst-API aufrufen muss – wie SQL Server.
Anstatt die Identität der aufrufenden Anwendung zu verwenden, wird die Identität (und die Berechtigungen) des delegierten Benutzers durch die Anforderungskette propagiert. Dazu authentifiziert sich die Anwendung der zweiten Schicht gegenüber der Ressource, z. B. einer SQL-Datenbank, mit ihrem eigenen Token, einem so genannten „On-behalf-of“-Token, das von der Anwendung der ersten Schicht stammt.
Dies ist ein Beispiel für die Delegation auf Identitätsebene.

Delegation von Befugnissen im SQL-Bereich

In SQL Server gibt es mehrere Möglichkeiten, die Delegation zu implementieren.

Erstellung von Azure AD-Benutzern

Ein Szenario, in dem die Delegation im Verborgenen genutzt wird, ist das folgende:
Angenommen, ein AAD-Principal, z. B. das AAD-Admin-Konto für Azure SQL, möchte einen AAD-Benutzer in der Datenbank anlegen (Anweisung: CREATE USER FROM EXTERNAL PROVIDER).
In diesem Fall wird die Managed Service Identity (MSI) benötigt, die dem Azure SQL Server zugeordnet ist. Mit dieser MSI sendet der Azure SQL Server die Informationen über den AAD-Benutzer, den das AAD-Administratorkonto als Benutzer innerhalb von SQL anlegen möchte, zur Überprüfung an den AAD-Graph (zukünftig: MS-Graph). Daher benötigt das MSI (und nicht das AAD-Admin-Konto) die entsprechende Berechtigung in Azure AD (z. B. die Rolle „Directory Readers“).

GRANT MIT GRANT OPTION

Dies ist vielleicht eine weniger bekannte Möglichkeit in SQL: Es ist möglich, Benutzern ein Recht zu gewähren und ihnen zu erlauben, dieses Recht weiterzugeben. Dafür ist die „WITH GRANT OPTION“ der GRANT-Anweisung gedacht.
Im folgenden Beispiel wurden dem Benutzer Shakti die verschiedenen Rechte INSERT, UPDATE, DELETE und SELECT auf ein Schema namens „Sales“ gewährt. Darüber hinaus ist es ihr durch die Verwendung der WITH GRANT OPTION erlaubt, diese Berechtigungen weiterzugeben.
Dies wird demonstriert, indem wir ihr Konto mit der EXECUTE AS-Klausel „impersonaten“ (übrigens: dies ist auch ein Beispiel für die Verwendung von Delegation auf der Identitätsebene) und nun „als“ Shakti Berechtigungen an eine andere Person, in diesem Fall Jiao, vergeben können.

SQLSecurity_Delegation_GrantWithGrantOption
EXECUTE AS und „privilege bracketing“ zum temporären Delegieren von Berechtigungen

Eine mächtige und häufig verwendete Technik ist die Möglichkeit, Stored Procedures unter einem separaten Benutzerkonto nur für die jeweilige Aufgabe auszuführen, unabhängig davon, wer der ursprüngliche Aufrufer ist, und so die Rechte des impersonierten Kontos für die Laufzeit der Stored Procedure zu nutzen.
Dies wird typischerweise verwendet, um Aufgaben zu delegieren, die sonst hohe Privilegien im SQL Server erfordern und hilft so, das Principle of Least Privilege zu wahren.
Streng genommen geschieht die Delegation, wenn der Zugriff auf die gespeicherte Prozedur gewährt wird. Die Verwendung einer gespeicherten Prozedur ist technisch gesehen ein separates Konzept, das als „Privilege Bracketing“ bezeichnet wird und in gewisser Weise in den gleichen Bereich fällt wie Just-in-Time-Privilegien (JIT). JIT ist eine weitere Technik, die die Verwendung bestimmter erhöhter Berechtigungen nur für einen bestimmten Zeitraum (aka „zeitlich begrenzt“) erlaubt.
Privileged Identity Management in Azure bietet diese Möglichkeiten: Was ist Privileged Identity Management? – Azure AD | Microsoft Docs

Siehe das untenstehende Beispiel: ALTER ist die minimale („least“) Berechtigung, die zum Aktualisieren von Statistiken auf Tabellen erforderlich ist. Aber anstatt ALTER für jede Tabelle oder die gesamte Datenbank zu gewähren, erhält Jiao nur die Erlaubnis, diese gespeicherte Prozedur auszuführen, die wiederum unter erhöhten Rechten läuft, die nur für die Laufzeit der Prozedur angenommen werden.

SQLSecurity_Delegation_ExecuteAs

Hinweis

Wenn man Aktivitäten von Benutzern auditiert (was man absolut sollte, aber das ist ein anderes Thema), muss man sich darüber im Klaren sein, dass – da Impersonation den Effekt hat, dass der „aktuelle Benutzer“ nicht der tatsächlich handelnde Benutzer ist – die Betrachtung nur der Server- oder Datenbank-Principal-IDs nicht das richtige Bild ergibt. Glücklicherweise erfasst SQL Auditing von Haus aus immer den session_server_principal_name. Dieser enthält den Namen des Principals, der ursprünglich mit der Instanz von SQL Server verbunden ist, unabhängig davon, wie viele Ebenen von Impersonation durchgeführt werden. Dies ist dasselbe wie die Verwendung der SQL-Funktion ORIGINAL_LOGIN(), die man bei der Implementierung benutzerdefinierter Protokollierungslösungen verwenden sollte.

Signieren von Modulen zum temporären Delegieren von Berechtigungen

Es gibt eine alternative Option zu „EXECUTE AS“ bei der Verwendung von Modulen für die Delegation: das Signieren des Moduls. In SQL Server können Module (wie gespeicherte Prozeduren, Funktionen und Trigger) mit einem asymmetrischen Schlüssel oder einem Zertifikat (technisch gesehen nur eine andere Form des asymmetrischen Schlüssels) signiert werden.
Der Trick ist, dass dieser Schlüssel oder dieses Zertifikat einem Datenbankbenutzer zugeordnet werden kann. Und wenn das Modul ausgeführt wird und die Signatur verifiziert wurde, erbt das Modul die Berechtigungen des zugeordneten Benutzers. Und hier liegt der Unterschied zur EXECUTE AS-Klausel: Die Berechtigungen des dem Zertifikat zugeordneten Benutzers werden zu den Berechtigungen des ursprünglichen Aufrufers hinzugefügt – sie ersetzen diese nicht. Das liegt daran, dass sich der Ausführungskontext nicht wirklich ändert. Das führt zum zweiten großen Unterschied: Alle eingebauten Funktionen, die Login- und Benutzernamen zurückgeben, geben den Namen des Aufrufers zurück, nicht den Zertifikatsbenutzernamen.
In den Ressourcen sind eine Reihe von Links mit verschiedenen Beispielen.

Hier ist ein Diagramm, das zeigt, wie dies in einem einfachen Beispiel verwendet werden kann:

In diesem Beispiel hat Ben allein nur SELECT auf die Tabelle Orders, hat aber keinen Zugriff auf die OrderDetails-Tabelle. Stattdessen ist vorgesehen, dass er nur über die speziell vorbereitete gespeicherte Prozedur ProcAccountforInternalCalc auf diese Tabelle zugreifen kann.
Erst zur Laufzeit dieser Prozedur werden die Rechte des ursprünglichen Aufrufers Ben um die Rechte eines anderen Benutzers, ProcAccountforInternalCalc, erweitert, der speziell für diesen Anwendungsfall angelegt wurde: um das SELECT-Recht auf die Tabelle OrderDetails nur dann zu gewähren, wenn die Stored Procedure sel_OrderDetails_with_margin verwendet wird. Dazu wird dieser Benutzer auf ein Zertifikat gemapped, Cert_ProcAccountforInternalCalc, das zum Signieren der gespeicherten Prozedur verwendet wurde.
Nun erbt jeder, der die Berechtigung hat, diese Prozedur auszuführen, die zusätzlichen Berechtigungen von ProcAccountforInternalCalc und kann dann die Daten aus der Tabelle sehen – nur unter Verwendung der Geschäftslogik aus der Prozedur.

Hinweis
Das Signieren von Modulen sollte nur verwendet werden, um Berechtigungen zu erteilen (GRANT) und nicht als Mechanismus um DENY’s zu erzwingen, geschweige denn Rechte zu revoken.

Die meisten SQL Server-Umgebungen, die ich gesehen habe, nutzen diese Konzepte bereits auf die eine oder andere Weise. Die Delegation ist eine immens mächtige und nützliche Technik: Wie Sie vielleicht aus den letzten beiden Beispielen erkennen, können diese Techniken auch dabei helfen, das Prinzip des geringsten Privilegs (Principle of Least Privilege) einzuhalten. Und sie kann auch helfen, Separation of Duties zu implementieren, was der Grund dafür ist, dass wir darüber speziell im Kontext der allgemeinen Sicherheitsprinzipien sprechen.

Die T-SQL Code-Beispiele sind als Download unterhalb dieses Artikels verfügbar.

Viel Spaß beim Delegieren

Andreas

Vielen Dank an meinen Reviewer:

Mirek Sztajno, Senior Program Manager in SQL Security und Experte in Authentifizierung