Saschas Weblog

ESCde Developer Blog

  Home :: Kontakt :: RSS Feed
  30 Posts :: 0 Artikel :: 10 Kommentare :: 32 Trackbacks

Archiv

Post Kategorien

ESCde

ESCde Blogger

Das Thema Security war im .NET Framework 1.x primär auf Code Access Security (CAS), Kryptographie und Sicherheit in ASP.NET Anwendungen beschränkt. Für andere wichtige Bereiche, wie etwa Manipulation von Berechtigungen auf Dateiebene oder auf Registryschlüssel (Access Control), musste man sich mit dem Import und Aufruf von Windows API Funktionen auseinander setzen.

Das .NET Framework 2.0 schafft hier Abhilfe: fast 70 Klassen und Enumerationen stehen im neuen Namespace System.Security.AccessControl zur Verfügung.

Zur Auffrischung noch mal ein kurzer Überblick über DACLs, SACLs, ACLs, ACEs, ...
Für detaillierte Informationen sei auf die Win32 API SDK Dokumentation  verwiesen.

Mit Access Control (Windows-Zugriffssteuerungssicherheit) kann der Zugriff auf verschiedene Objekte, auch Securable Objects genannt, gesichert werden. Zu diesen Objekten gehören unter anderem Dateien und Verzeichnisse auf NTFS-formatierten Festplatten, Registryschlüssel, Windowsdienste, Drucker, Netzwerkfreigaben und auch Active Directory-Objekte.  Mit jedem dieser Objekte kann Windows einen sogenannten Security Descriptor (SD) verknüpfen.

Der Security Descriptor enthält einen Hinweis auf den Besitzer des Objekts, eine Discretionary Access Control List (DACL) und eine System Access Control List (SACL). Die DACL besitzt ein oder mehrere Elemente, die den Zugriff auf das Objekt steuern. In der SACL befinden sich ein oder mehrere Elemente, die die Ereignisprotokollierung beim Zugriff auf das Objekt steuern.

DACL und SACL sind Beispiele für Access Control Lists (ACL). ACLs bestehen wiederum aus einem oder mehreren Access Control Entries (ACE). Die Rechte, die ein ACE konfigurieren kann, hängen von dem jeweiligen zu sichernden Objekt ab; gängige Rechte sind z.B. Lesen, Schreiben oder Löschen. Ein ACE kann ein solches Recht erlauben (allow) oder verbieten (deny). DACLs bestehen also aus zwei Kategorien von ACEs: Access-Allowed-ACEs und Access-Denied-ACEs. Das fehlende Teil im Access-Control-Puzzle ist der Security Identifier (SID). Mit Hilfe von einem SID kann der ACE das konfigurierte Recht auf einen Windowsbenutzer oder eine Windowsgruppe abbilden.  

Neben dem neuen Namespace wurden auch einige, schon in .NET 1.x vorhandene Klassen um entsprechende Methoden erweitert. So bieten etwa System.IO.File und Microsoft.Win32.RegistryKey je zwei neue Methoden GetAccessControl und SetAccessControl, mit deren Hilfe sich die Zugriffssteuerungssicherheit auslesen bzw. schreiben lässt.

Zugriffssteuerungssicherheit im Dateisystem

Um die ACE Einträge einer Datei anzuzeigen, wird zunächst die statische GetAccessControl Methode der System.IO.File Klasse aufgerufen, die ein Objekt vom Typ System.Security.AccessControl.FileSecurity zurückgibt, welches sowohl die DACL als auch die SACL der gewählten Datei enthält.

Die FileSecurity Klasse enthält eine Methode GetAccessRules, die die Discretionary ACL der Datei zurückgibt. Mit SetAccessRules kann die geänderte DACL  zurückgeschrieben werden. Die System ACLs lassen sich entsprechend mit den Methoden GetAuditRules und SetAuditRules lesen und schreiben.

Die GetAccessRules Methode gibt ein Objekt vom Typ AuthorizationRuleCollection zurück. Diese Auflistung enthält ein oder mehrere AuthorizationRule Objekte. AuthorizationRule ist die abstrakte Basisklasse für AccessRule und AuditRule Klassen. So liefert die GetAccessRules Methode eines FileSecurity Objekts eine AuthorizationRuleCollection zurück, die aus einer Liste von FileSystemAccessRule Objekten besteht.

using System.Security.AccessControl; using System.Security.Principal; using System.Diagnostics; using System.IO; using Microsoft.Win32; … private DataTable ShowFileRights(string filename) { bool includeExplicit = true; bool includeInherited = true; // DataTable für Rückgabe vorbereiten DataTable dt = new DataTable("DACL"); dt.Columns.Add("AccessControlType", typeof(System.String)); dt.Columns.Add("IdentityReference", typeof(System.String)); dt.Columns.Add("FileSystemRights", typeof(System.String)); // Filesecurity-Objekt über System.IO.File abfragen System.Security.AccessControl.FileSecurity fileSec = System.IO.File.GetAccessControl(filename); // zu SID gehörigen NT Account in Ausgabe verwenden System.Type principalType = typeof(System.Security.Principal.NTAccount); // SID in Ausgabe verwenden //System.Type principalType = typeof(System.Security.Principal.SecurityIdentifier); System.Security.AccessControl.AuthorizationRuleCollection rules = fileSec.GetAccessRules( includeExplicit, // true, um explizit für das Objekt festgelegte Zugriffsregeln einzuschließen. includeInherited, // true, um geerbte Zugriffsregeln einzuschließen. principalType); // alle Ruleobjekte durchlaufen foreach (FileSystemAccessRule rule in rules) { DataRow dr = dt.Rows.Add(); dr["AccessControlType"] = rule.AccessControlType.ToString(); dr["IdentityReference"] = rule.IdentityReference.Value; dr["FileSystemRights"] = rule.FileSystemRights.ToString(); } // DataTable mit ACL zurückgeben return dt; }

Wenn wir das Beispiel in einer Windows Forms Anwendung starten und die zurückgegebene DataTable an ein DataGridView-Steuerelement binden, sieht das fast schon ganz übersichtlich aus.

Wie weiter oben erwähnt, funktioniert Zugriffssteuerungssicherheit im Dateisystem nur mit NTFS-formatierten Festplatten. Evtl. sollte also eine Überprüfung des Plattenformats durchgeführt werden. Das lässt sich mit einem Zweizeiler erledigen:

private bool IsNtfsDrive(string fileName) { // DriveInfo Instanz aus übergebenem Dateinamen erzeugen System.IO.DriveInfo di = new DriveInfo(fileName); // DriveFormat Eigenschaft liefert "NTFS" oder "FAT32" return (di.DriveFormat == "NTFS"); }
Zugriffsteuerungssicherheit von Registryschlüssel

Das Auslesen der Zugriffsteuerungssicherheit von Registryschlüssel verläuft fast identisch:

Hier wird zunächst die GetAccessControl Methode des RegistryKey Objektes aufgerufen, die ein Objekt vom Typ System.Security.AccessControl.RegistrySecurity zurückgibt. Um die Rückgabe der Methode auf die DACL zu beschränken, wird GetAccessControl der Parameter AccessControlSections.Access mitgegeben.

Die RegistrySecurity Klasse enthält eine Methode GetAccessRules, die die Discretionary ACL der Datei zurückgibt.

Die GetAccessRules Methode gibt ein Objekt vom Typ AuthorizationRuleCollection zurück. Diese Auflistung enthält ein oder mehrere AuthorizationRule Objekte. Die AuthorizationRuleCollection der RegistrySecurity Klasse besteht aus einer Liste von RegistryAccessRule Objekten.

private DataTable ShowRegistryRights(string keyname) { bool includeExplicit = true; bool includeInherited = true; // DataTable für Rückgabe vorbereiten DataTable dt = new DataTable("DACL"); dt.Columns.Add("AccessControlType", typeof(System.String)); dt.Columns.Add("IdentityReference", typeof(System.String)); dt.Columns.Add("RegistryRights", typeof(System.String)); // Registrykey öffnen RegistryKey theKey = Registry.LocalMachine.OpenSubKey(keyname); // RegistrySecurity-Objekt abfragen, gleich auf DACL beschränken System.Security.AccessControl.RegistrySecurity regSec = theKey.GetAccessControl(AccessControlSections.Access); // zu SID gehörigen NT Account in Ausgabe verwenden System.Type principalType = typeof(System.Security.Principal.NTAccount); // SID in Ausgabe verwenden //System.Type principalType = typeof(System.Security.Principal.SecurityIdentifier); System.Security.AccessControl.AuthorizationRuleCollection rules = regSec.GetAccessRules( includeExplicit, // true, um explizit für das Objekt festgelegte Zugriffsregeln einzuschließen. includeInherited, // true, um geerbte Zugriffsregeln einzuschließen. principalType); // alle Ruleobjekte durchlaufen, diesmal vom Typ RegistryAccessRule foreach (RegistryAccessRule rule in rules) { DataRow dr = dt.Rows.Add(); dr["AccessControlType"] = rule.AccessControlType.ToString(); dr["IdentityReference"] = rule.IdentityReference.Value; dr["RegistryRights"] = rule.RegistryRights.ToString(); } // DataTable mit ACL zurückgeben return dt; }

veröffentlicht am 19.07.2006 10:19