Angesichts der „Folterwerkzeuge“, die im .NET Framework im Bereich der Code Access Security (CAS) versteckt sind [1], wird sich der eine oder andere Entwickler wehmütig an die gute alte Zeit zurückerinnern. Damals stellte eine frische Standardinstallation von Windows alle Dienstleitungen sofort zur Verfügung, sehr zur Freude der generell von Zeitnot geplagten Entwickler und Anwender. Allerdings freute sich da still und heimlich noch eine andere Klientel, was sich dann regelmäßig in Form von Fieberschüben aufgrund von Viren, Würmern oder sonstigem Getier bemerkbar machte. Mit dem .NET Framework begann eine neue Ära, in der einer ausführbaren Anwendung bereits in der Voreinstellung je nach Herkunft enge Fesseln angelegt werden. Während zuerst nur der Entwickler von diesem Paradigmenwechsel betroffen war, spürten beginnend mit Windows 2003 Server die Administratoren ebenfalls den frischen Wind. Auch wenn der Aufwand für beide steigt, will doch wohl niemand die guten alten (unsicheren) Zeiten wirklich zurück haben. Da die Benutzerfreundlichkeit (um nicht das unschöne Wort „Bequemlichkeit“ in den Mund nehmen zu müssen) aber eines der Geheimnisse für den Erfolg des Betriebssystems Windows war, sieht auch das .NET Framework einen bequemen Weg vor, solange die .NET-Anwendung von einem lokalen Laufwerk des Rechners aus gestartet wird. Dank der vom .NET Framework in den Namespaces System.Reflection, System.Security, System.Security.Policy und System.Security.Permissions bereitgestellten Klassen kann die Beispielanwendung in diesem Fall den Ausstattungsgrad des eigenen Sandkastens ermitteln, weil die Anwendung von der CLR (Common Language Runtime) mit uneingeschränkten Berechtigungen (FullTrust) ausgeführt wird. Die vom Beispielprogramm angezeigten Informationen fasst die folgende Aufzählung zusammen (der Kasten „Code Access Security (CAS) im Schnelldurchlauf“ hilft bei der Einordnung der Begriffe):
- Aufrufpfad des Programms.
- Name der Zone, in die die Anwendung von der CLR eingeordnet wurde.
- Dateinamen der verschiedenen Konfigurationsdateien für die Sicherheitseinstellungen.
- Zuordnung der Berechtigungsgruppen getrennt nach Computer (Machine) Organisation (Enterprise) und Benutzer (User), wobei der niedrigste Berechtigungssatz das Verhalten der Anwendung definiert (Prinzip des kleinsten gemeinsamen Nenners der Berechtigungen).
- Aktuelle Berechtigungsmenge.
- Benutzername im Active Directory.
Über die Codezugriffssicherheit steht ein Modell zur Verfügung, über das ein Administrator eigene Sicherheitsrichtlinien für den Zugriff auf Ressourcen oder das Ausführen von privilegierten Anweisungen direkt dem ausführbaren Modul zuordnen kann. Während das Betriebssystem bisher die Rechte bei den Win32-Anwendungen generell dem Benutzerkonto zugeordnet hat, erlaubt die CAS eine viel feinere Abstufung, da nun zum Beispiel auch die Fragen „Von wo aus wurde die Assembly geladen?“, „Von wem stammt die Assembly?“ oder gar „Welche Anwendung ruft diese Assembly auf?“ bei der Vergabe der Berechtigungen (Permission) berücksichtigt werden. Unter einer Berechtigung versteht man das Recht, eine so genannte Trusted Operation (wie zum Beispiel der Zugriff auf das Dateisystem, die Registry, die Ereignisanzeige, die Umgebungsvariablen oder gar auf die Benutzeroberfläche usw.) ausführen zu dürfen. Die Sicherheitsprüfung ist ein Kernbestandteil der CLR, sowohl der für das Laden einer Klasse zuständige Class Loader als auch der Just-in-Time-Compiler (JIT) beachten die CAS-Regeln. Bei der Frage, wie eine Berechtigung genutzt wird, kommen die Aktionen Demand, Assert, Deny, PermitOnly und LinkDemand ins Spiel. Eine Sicherheitsüberprüfung für das Berechtigungsobjekt kann über Demand angefordert oder über Assert teilweise blockiert werden. Über einen LinkDemand wird direkt am JIT die Prüfung des unmittelbaren Aufrufers beauftragt, sodass in Verbindung mit einer StrongNameIdentityPermission eine Klasse sicherstellt, dass sie nur von einem definierten Nutzer (Strong Name) eingebunden wird. Wenn .NET eine Assembly lädt, wird der Beweis (Evidence) über die Codeherkunft ermittelt, damit .NET genau die Berechtigungsmenge (Permission Set) der Privilegien zusammenstellen kann, die für diese Herkunft über die Sicherheitsrichtlinien (Policy) festgelegt wurden. Die CLR berücksichtigt sieben verschiedene Evidence-Typen, wobei vier davon (Site, Url, Zoneund ApplicationDirectory) die Herkunft des ausführbaren Programmcodes berücksichtigen. Die beiden Evidence-Typen StrongName und Publisherbeantworten die Frage, welcher Entwickler diesen Code geschrieben hat. Der verbleibende Evidence-Typ Hash (SHA1 mit einem 20-Byte-Hashcode) wird aus der Prüfsumme der Assembly gebildet und erlaubt die Prüfung auf eine bestimmte (nicht manipulierte) Codeversion, unabhängig von der offiziellen Versionsnummer. Diese sieben Evidence-Typen werden auch als Host Evidence bezeichnet, da die Host-Umgebung für die Implementierung zuständig ist. Unter .NET gibt es zwei Instanzen, die diese Beweise für die Vertrauenswürdigkeit sammeln können: Zum einen die CLR selbst und zum anderen der Host der Application Domain (also die Stelle, die eine Assembly lädt und ausführen lässt). Es dürfen nur diejenigen Beweise vorbringen, die als vertrauenswürdig (Sicherheitsrecht ControlEvidence) eingestuft wurden. Zurzeit berücksichtigt .NET gleich drei Hosts automatisch, neben der Windows-Shell und dem Internet Explorer darf auch ASP .NET die Beweise vorlegen. Damit die Berechtigungsmengen nicht mühsam jeder einzelnen Assembly zugeordnet werden müssen, unterteilt die CLR die Welt in fünf verschiedene vordefinierte Sicherheitszonen (Code Groups), wobei in der Zone My_Computer_Zone alle die Assemblies landen, die von einem lokalen Datenträger aus geladen wurden:
- My_Computer_Zone
- LocalIntranet_Zone
- Trusted_Zone
- Internet_Zone
- Restricted_Zone
In der LocalIntranet_Zone landen in der Voreinstellung alle die Assemblies von einem entfernten Dateisystem, die über ein gemapptes Netzlaufwerk, einen UNC-Pfad (wie zum Beispiel \\Servername\Freigabename\AssemblyName. dll) oder über eine HTTP-URL für WINS-Adresssen (wie z.B. http:// ServerName/VirtuellesWebverzeichnis/AssemblyName.dll) geladen werden. In der Zone Internet_Zone landen alle Assemblies, die keiner anderen Zone zugeordnet werden können. Beachten Sie bitte, dass dies auch für alle URLs gilt, bei denen die IP-Adresse genutzt wird (somit unterscheiden sich http://localhost und http://127.0.0.1 in der Zuordnung, obwohl beide ULRs den gleichen Rechner adressieren). Zusätzlich zu den vordefinierten Codegruppen können eigene Gruppen eingerichtet werden, wobei für diesen Schritt verschiedene Wege verfügbar sind. Zum einen die visuelle Konfiguration über die .NET Framework Configuration, die Script-Konfiguration über das Kommandozeilen-Tool Caspol.exe und als dritte Option das direkte Hantieren mit der SecurityManager-Klasse aus dem .NET-Framework. Jeder Codegruppe können Berechtigungsmengen (Permission Sets) zugeordnet werden, um auch bei den Berechtigungen nicht alles einzeln konfigurieren zu müssen. Die CLR stellt eine Menge von vordefinierten unveränderlichen Permission Sets zur Verfügung, die jedoch in Form einer Kopie erweitert werden können. Zum Beispiel enthält das Internet-Permission-Set alle die Berechtigungen, die für den Download aus dem Internet gelten sollen. Im Gegensatz dazu sorgt das FullTrust-Permission-Set dafür, dass der Programmcode alle Operationen uneingeschränkt ausführen darf.
Listing 1--------------------------------------------------------StatusBarMain.Text = String.Format( _"Im Active Directory angemeldet als Benutzer"{0}"", _Environment.UserName)‚Dim aAsm As System.Reflection.AssemblyaAsm = System.Reflection.Assembly.GetExecutingAssembly()LabelAsm.Text = aAsm.CodeBase.ToString()‚Dim sBD As String = AppDomain.CurrentDomain.BaseDirectoryDim aSZ As SecurityZone = Zone.CreateFromUrl(sBD).SecurityZoneLabelSecurityZone.Text = aSZ.ToString()
Listing 2--------------------------------------------------------------UnionCodeGroup['All_Code']:FullTrustUnionCodeGroup['All_Code']:NothingUnionCodeGroup['My_Computer_Zone']:FullTrustUnionCodeGroup['All_Code']:FullTrust
Sysadmin – wir haben ein Problem
Wird die Programmdatei nun auf die Festplatte des Servers verschoben und über ein gemapptes Netzlaufwerk gestartet, so scheint zuerst alles noch in Ordnung. Doch bereits die geänderte Zone (Intranet anstelle von MyComputer) gibt einen ersten Hinweis auf die Probleme, die nach dem Anfordern aller Daten deutlich werden. Die CLR würgt diesen Informationswunsch mit einem Veto vom Typ System.Security.Permissions.SecurityPermission ab, da das Benutzerkonto allein nicht mehr die verfügbaren Berechtigungen festlegt (Abbildung 1). &picture_0 Das Beispielprogramm kann beim Start über das Netzlaufwerk erst dann zur uneingeschränkten Kooperation überredet werden, wenn mit Administratorrechten über die .NET-Framework-Konfiguration unterhalb von All_Code eine neue Codegruppe angelegt wird. Als kennzeichnendes Merkmal, über das eine Assembly dieser neuen Codegruppe automatisch zugeordnet werden soll, wurde im Beispiel der Strong Name ausgewählt, mit dem die Beispielanwendungen (Visual-Basic- und C#-Fassung) signiert wurden (Abbildung 2).
Listing 3---------------------------------------------------------UnionCodeGroup['All_Code']:FullTrustUnionCodeGroup['All_Code']:NothingUnionCodeGroup['LocalIntranet_Zone']:LocalIntranetUnionCodeGroup['dotnetMagazin']:FullTrustUnionCodeGroup['All_Code']:FullTrust
- In einem Firmennetzwerk ist der Administrator in der Lage, die einmalig von Hand zusammengestellte Richtlinienstruktur über den Weitergabepaketassistenten der .NET-Framework-Konfiguration als MSI-Setup zusammenzupacken. Dieses Setup überschreibt dann bei den zu konfigurierenden Rechnern die Standardeinstellung durch die definierte Richtlinienstruktur des Unternehmens.
- Während der Weitergabepaketassistent der .NET-Framework-Konfiguration eine „Alles-oder-Nichts“-Lösung ist, erlaubt das Kommandozeilen-Tool Caspol.exe einen „chirurgischen“ Eingriff, indem ein Skript die Konfiguration von einer zusätzlichen Codegruppe übernimmt.
- Das Installationsprogramm der .NET-Anwendung (MSI-Setup) wird um eine Installer-Klasse erweitert, die die benötigte Codegruppe während des Setups anlegt. Allerdings gilt auch hier, dass zur Änderung der Computerberechtigungsgruppen für das Setup Administratorrechte benötigt werden.
Das Setup-Projekt
Von den verfügbaren Optionen erfüllt das MSI-Setup der Beispielanwendung die Anforderungen am besten – denn im Normalfall soll die Anwendung ja auch lokal installiert werden. Nur für den Fall, dass eine Unternehmensrichtlinie den lokalen Aufruf nicht vorsieht, wird die Codegruppe für FullTrust-Berechtigung angelegt, sodass die Anwendung auch dann noch problemlos aufgerufen werden kann, wenn diese nur von einem Netzlaufwerk aus gestartet werden soll. Nachdem das Grundgerüst des Setup-Projekts steht, wird der Projektmappe ein weiteres Projekt für eine Klassenbibliothek hinzugefügt. Damit das MSI-Setup die neue Klasse einbindet, muss diese von System.Configuration.Install.Installer abstammen und mit dem Attribut [RunInstaller(true)] gekennzeichnet werden.
- Es wird ein sprechender, eindeutiger Name für die neue Codegruppe festgelegt.
- Weil der Strong Name für die Zuordnung herangezogen werden soll, muss nun auf StrongNameMembershipCondition zurückgegriffen werden. Über die StrongNamePublicKeyBlob-Klasse werden die öffentlichen Schlüsselinformationen des Strong Name aufbereitet, wobei die Rohdaten vom Kommandozeilen- Tool secutil.exe stammen. Mit dem Aufruf "secutil -c -s VBWinApp. exe > output.txt" schreibt dieses Tool die gesuchte Information in eine Datei, wobei dann die Public-Key-Zeichenkette über die Zwischenablage in das Klassenbibliotheksprojekt kopiert wird.
- Die Klassenbibliothek wird mit in das Setup-Projekt aufgenommen.
- Im Setup-Projekt wird der Custom-Actions-Editor aufgerufen, um jeweils in den Ordnern Install, Commit und Uninstall einen Verweis auf die Klassenbibliothek mit der Installer-Klasse hinzuzufügen (Abbildung 3).
Links & Literatur
- Brian A. LaMacchia et al., .NET Framework Security, Addison-Wesley 2002
- Andreas Kosch, Managed Bodyguard, in: dot.net magazin 6.05
- http://www.windowsforms.net/Applications/application.aspx?PageID=40&tabindex=8
- Don Box zum Thema CAS-Security




