Wie kann eine mit PERMISSION_SET =SAFE erstellte CLR-Assembly möglicherweise auf externe Systemressourcen zugreifen, nicht verwalteten Code aufrufen und Systemadministratorrechte erwerben?
Dies ist auf Sicherheitsänderungen zurückzuführen, die in .NET Framework ab Version 4.5 (glaube ich) vorgenommen wurden.
In der MSDN-Dokumentation für Code Access Security Basics heißt es:
Das .NET Framework bietet einen Mechanismus für die Erzwingung unterschiedlicher Vertrauensebenen für unterschiedlichen Code, der in derselben Anwendung ausgeführt wird, der als Code Access Security (CAS) bezeichnet wird. Die Codezugriffssicherheit in .NET Framework sollte nicht als Mechanismus zum Erzwingen von Sicherheitsgrenzen basierend auf Codeursprung oder anderen Identitätsaspekten verwendet werden. Wir aktualisieren unsere Leitlinien, um zu verdeutlichen, dass Codezugriffssicherheit und sicherheitstransparenter Code nicht als Sicherheitsgrenze mit teilweise vertrauenswürdigem Code unterstützt werden, insbesondere mit Code unbekannter Herkunft. Wir raten davon ab, Code unbekannter Herkunft zu laden und auszuführen, ohne alternative Sicherheitsmaßnahmen zu ergreifen.
Und zeigt dann auf die Seite für Sicherheitsänderungen in .NET Framework, auf der es heißt:
Die wichtigste Sicherheitsänderung in .NET Framework 4.5 betrifft die starke Benennung.
Was dann auf die Dokumentation für Enhanced Strong Naming verweist, in der es heißt:
Starke Namensschlüssel bestehen aus einem Signaturschlüssel und einem Identitätsschlüssel. Die Baugruppe wird mit dem Signaturschlüssel signiert und durch den Identitätsschlüssel identifiziert. Vor .NET Framework 4.5 waren diese beiden Schlüssel identisch. Ab .NET Framework 4.5 bleibt der Identitätsschlüssel derselbe wie in früheren .NET Framework-Versionen, aber der Signaturschlüssel wird durch einen stärkeren Hash-Algorithmus erweitert. Zusätzlich wird der Signaturschlüssel mit dem Identitätsschlüssel signiert, um eine Gegenzeichnung zu erstellen.
AUCH heißt es in der Dokumentation zu den Richtlinien für die sichere Codierung:
Codezugriffssicherheit und sicherheitstransparenter Code werden nicht als Sicherheitsgrenze mit teilweise vertrauenswürdigem Code unterstützt. Wir raten davon ab, Code unbekannter Herkunft zu laden und auszuführen, ohne alternative Sicherheitsmaßnahmen zu ergreifen...
Das Sicherheitsmodell für .NET hat sich also vor Jahren geändert, aber SQL Server (bis SQL Server 2017) durfte das alte Sicherheitsmodell weiterhin verwenden. Es scheint, dass ab SQL Server 2017 die Entscheidung getroffen wurde, das alte Sicherheitsmodell nicht mehr zu unterstützen.
Ich vermute, dass das alte Sicherheitsmodell zugelassen wurde:
-
Verhindern, dass SQL Server (zumindest die CLR-bezogenen Funktionen / Komponenten) auf den neueren .NET Framework-Versionen basieren, und
-
verantwortlich für die abrupte Entfernung von SQLCLR als unterstütztes Feature aus der Azure SQL-Datenbank (Unterstützung wurde Ende 2014 mit dem Start von v12 hinzugefügt, dann aber am 15. April 2016 vollständig entfernt).
Also, ja, das ist irgendwie scheiße. Was es bedeutet (zumindest im Moment) ist, dass man zuerst muss Erstellen Sie ein Zertifikat oder einen asymmetrischen Schlüssel (der verwendet wurde, um alle zu ladenden Assemblies zu signieren) in [master]
um dann ein Login zu erstellen und dann UNSAFE ASSEMBLY
zu gewähren zu diesem Login. Dies ist dieselbe Abfolge von Ereignissen, die man beim Laden von EXTERNAL_ACCESS
ausführen muss und UNSAFE
Assemblies, die aber jetzt leider auch noch SAFE
gemacht werden müssen Versammlungen.
Es gibt derzeit keinen Mechanismus, um dies vollständig portabel zu handhaben (d. h. sich nicht auf externe Dateien zu verlassen) und kann von Visual Studio / SSDT nicht ohne manuellen Eingriff gehandhabt werden. Das war ein bisschen schon der Fall, aber zumindest war es möglich, ein Setup zu erstellen, um dies auf vollständig portierbare Weise zu handhaben (d. h. vollständig in einem .sql-Skript enthalten):Einzelheiten finden Sie unter Stairway to SQLCLR Level 7:Development and Security (dies ist ein Artikel, den ich geschrieben habe).
Es ist möglich, ein Zertifikat aus Hex-Bytes zu erstellen (z. B. FROM BINARY = 0x...
), aber das funktioniert nicht mit Visual Studio (das auf MSBuild basiert) / SSDT, da die Verwendung des Zertifikats die Verwendung von signtool
erfordert und MSBuild verwendet sn
.
Damit dies so funktioniert, dass der Veröffentlichungsprozess von Visual Studio / MSBuild / SSDT funktioniert (was wiederum bedeuten würde, dass jeder in der Lage wäre, ein vollständig eigenständiges .sql-Skript zu erstellen, das in der Lage wäre, den asymmetrischen Schlüssel zu erstellen, ohne sich darauf zu verlassen eine externe Datei), den CREATE ASYMMETRIC KEY
Der Befehl muss erweitert werden, damit er aus einer binären Zeichenfolge erstellt werden kann. Ich habe diesen Vorschlag auf Microsoft Connect gemacht – Lassen Sie zu, dass asymmetrische Schlüssel aus einer binären Hex-Byte-Zeichenfolge erstellt werden, genau wie CREATE CERTIFICATE – also unterstützen Sie ihn bitte :-).
Alternativ (für den Moment, bis MS hoffentlich eine bessere Methode entwickelt, wie meine Vorschläge für asymmetrische Schlüssel), können Sie eine der beiden Techniken ausprobieren, die ich in den folgenden Blogbeiträgen beschreibe (beide funktionieren vollständig mit SSDT):
- SQLCLR vs. SQL Server 2017, Teil 2:„Strikte CLR-Sicherheit“ – Lösung 1
- SQLCLR vs. SQL Server 2017, Teil 3:„Strikte CLR-Sicherheit“ – Lösung 2
Als letztes Resort, können Sie den folgenden Ansatz in Betracht ziehen:
-
VORÜBERGEHEND setze den
[master]
Datenbank aufTRUSTWORTHY ON
Für den nächsten Schritt (also
CREATE ASSEMBLY
), um erfolgreich ausgeführt zu werden, die Anmeldung, die der Datenbankeigentümer ist (d. h. dieselbe SID, die von[dbo]
verwendet wird Benutzer von[master]
) muss denUNSAFE ASSEMBLY
haben Erlaubnis. Wenn[master]
gehörtsa
oder irgendein anderer Sysadmin, dann hat er alle Rechte und diese Voraussetzung ist erfüllt. Aber wenn[master]
einer Anmeldung mit geringen Berechtigungen gehört (eine „Best Practice“), dann müssen Sie die folgende Anweisung ausführen, umCREATE ASSEMBLY
auszuführen funktionieren, wennTRUSTWORTHY
istON
:EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
- Erstellen Sie die Assembly in
[master]
- Erstellen Sie den asymmetrischen Schlüssel aus der Assembly
- Verwerfen Sie die Baugruppe
- den
[master]
einstellen Datenbank aufTRUSTWORTHY OFF
- Erstellen Sie das Login aus dem asymmetrischen Schlüssel
- Gewähren Sie
UNSAFE ASSEMBLY
zu diesem Login (dies ersetzt die Notwendigkeit, dass die DB, in die die Assembly geladen wird, aufTRUSTWORTHY ON
gesetzt werden muss und für seinen Besitzer Einloggen, um denUNSAFE ASSEMBLY
zu erhalten Erlaubnis).
Bitte beachten Sie, dass ich es nicht getan habe Fügen Sie hier optional das neue Feature "Trusted Assembly" hinzu. Der Grund, warum es nicht erwähnt wurde, liegt darin, dass es viel mehr Mängel als Vorteile hat, ganz zu schweigen davon, dass es von vornherein völlig unnötig ist, da die vorhandene Funktionalität bereits die Situation bewältigt, die „Vertrauenswürdige Assemblies“ ansprechen sollte. Ausführliche Informationen dazu und eine Demo zur richtigen Handhabung vorhandener, nicht signierter Assemblies finden Sie unter:SQLCLR vs. SQL Server 2017, Teil 4:„Vertrauenswürdige Assemblies“ – Die Enttäuschung.