Die Verwendung von JAAS in der Praxis

Erkannt und zugelassen

Wolfgang Korn

Mit dem Java Authentication and Authorization Service hat ein neues API seinen Weg in das aktuelle Release der Java 2 Standard Edition (J2SE) gefunden. Was dieses API leistet und wie es sich mit dem praktischen Einsatz verhält, wird im Rahmen des Artikels untersucht.

Benutzeranmeldungen und die Vergabe von Zugriffsrechten an Benutzer finden sich in nahezu allen größeren Business-Anwendungen. Dabei wird zunächst die Identität des Benutzers ermittelt, dieser Vorgang wird auch als Authentisierung des Benutzers bezeichnet. Das Ergebnis der Authentisierung entscheidet, ob dem Benutzer Zugriff auf das System gewährt wird oder ob der Zugang abgelehnt wird. Über diesen grundlegenden Zugangsschutz hinaus sind häufig weitergehende Berechtigungen mit der Identität eines Benutzers verbunden. So kann für jeden Benutzer detailliert festgelegt werden, welche Funktionalität des Systems genutzt werden darf. Diese Zuteilung von Berechtigungen an Benutzer wird als Autorisierung bezeichnet.

Komponenten zur Authentisierung von Benutzern werden in der Praxis häufig mit jeder neuen Anwendung neu entwickelt. Die Schnittstellen sind meist speziell auf die zugehörige Anwendung zugeschnitten und die entstehenden Komponenten somit nicht in anderen Anwendungen wieder verwendbar. Sollen in einer Anwendung weitere Techniken zur Benutzeridentifikation unterstützt werden, bedeutet dies immer die Neuentwicklung eines entsprechenden Moduls und dessen Integration in die bestehende Anwendung – Anwendungen sind damit nicht unabhängig von der verwendeten Login-Technologie. Ähnlich verhält es sich mit der Vergabe von Berechtigungen. Diese werden ebenfalls meist anwendungsspezifisch implementiert oder erfolgen vollständig außerhalb der Anwendung in den beteiligten Backend-Systemen.

Standardisierung

Die geschilderten Tatsachen zeigen die Notwendigkeit zur Definition einheitlicher Schnittstellen für Authentisierung und Autorisierung. Mit dem Java Authentication and Authorization Service (JAAS) hat Sun diesem Gedanken Rechnung getragen. Wie der Name erahnen lässt, besteht JAAS aus zwei wesentlichen Teilen.

Der für die Authentisierung zuständige Teil von JAAS stellt eine standardisierte Schnittstelle zur Verfügung, die durch Anwendungen zum Zugriff auf Authentisierungs-Dienste genutzt werden kann. Diese Schnittstelle ist völlig Technologie unabhängig. Die verschiedenen Verfahren zur Identifikation eines Benutzers werden dabei als Login-Module realisiert. Zur Verwendung einer neuen Identifikationsmethode (z.B. Smartcard anstelle von Benutzername/Passwort) können diese Module durch einen Administrator ausgetauscht werden. Anpassung oder Rekompilieren der Anwendung sind hierzu nicht notwendig. Vielmehr beschränkt sich der Austausch auf die Bereitstellung der benötigten .class-Dateien und die Konfiguration des Moduls in einer JAAS- Konfigurationsdatei. JAAS stellt hiermit eine Java-Implementierung des aus dem UNIX-Umfeld bekannten Pluggable Authentication Moduls (PAM) [7] dar.

Die Autorisierungskomponente ergänzt die in Java2 implementierten Code-zentrierten Mechanismen der Zugriffskontrolle um Benutzer-zentrierte Mechanismen. Ohne JAAS war die Vergabe von Zugriffsrechten in Java2 an die Herkunft des auszuführenden Codes gekoppelt (Codebase) oder/und an dessen Herausgeber (Signer). JAAS weitet dieses Konzept auf den Benutzer einer Anwendung aus – die Berechtigungen für sensible Operationen können damit in Abhängigkeit von der Identität des Ausführenden vergeben werden. Seit der Version 1.4.0 der Java-Plattform ist der Java Authentication and Authorization Service fester Bestandteil der Laufzeitumgebung. Für die ältere Version 1.3.* kann JAAS als Standard-Extension installiert werden; auch die Enterprise Edition der Java-Plattform verwendet JAAS als integralen Bestandteil für Authentisierung und Autorisierung. Für Client-, Web- und EJB-Container J2EE-konformer Produkte ist die Unterstützung von JAAS gemäß der Spezifikation verpflichtend.

Benutzerinformationen

Für Anwendungen, die eine auf JAAS basierende Benutzeranmeldung implementieren, stellt das API Klassen zur Verfügung, die dem Zugriff auf Informationen über den angemeldeten Benutzer einerseits und der Durchführung des Login-Vorgangs andererseits dienen.

Als zentrale Klasse zum Zugriff auf die im Rahmen des Logins ermittelten Benutzerinformationen stellt JAAS die Klasse Subject zur Verfügung. Ein Subject repräsentiert eine Instanz, welche im Rahmen des Login-Prozesses identifiziert wurde. Dabei kann es sich sowohl um Personen, als auch um Systeme handeln. Eine identifizierte Instanz verfügt über einen oder mehrere Namen. Diese werden in Klassen abgelegt, die das Interface Principal aus dem Paket java.security implementieren. Darüber hinaus sind mit einem Subject häufig auch sicherheitsrelevante Informationen verknüpft. Dabei kann es sich um öffentlich zugängliche Informationen wie Public Keys und Zertifikate oder auch um geheime Informationen wie Private Keys und Passworte handeln. Diese Informationen werden als Credentials bezeichnet. Credentials können beliebige Java-Objekte sein, für die es kein gemeinsam zu implementierendes Interface gibt.

Abb. 1: Klassen zum Zugriff auf Benutzerinformationen

Zur Durchführung des Login-Vorgangs stellt JAAS die Klasse LoginContext zur Verfügung. Das Codefragment in Listing 1 zeigt deren Verwendung. JAAS-basierte Anwendungen starten den Anmeldevorgang durch die Instanziierung eines LoginContextes. Der Parameter, der hierbei übergeben wird, verweist auf eine JAAS-Konfiguration. Wie später beschrieben wird, legt diese für die verschiedenen Anwendungen fest, welche Login-Module zu verwenden sind. Durch Aufruf der Methode login wird die Authentisierung unter Verwendung der konfigurierten Login-Module gestartet. Nach einer erfolgreichen Anmeldung kann über den LoginContext ein Subject ermittelt werden, welches die ermittelten Benutzerinformationen (Principals und Credentials) enthält. Misslungene Anmeldeversuche werden durch eine LoginException quittiert. Principals und Credentials, die im Rahmen der Authentisierung mit einem Subject verknüpft wurden, werden nach Aufruf der logout-Methode wieder gelöscht.

Listing 1: JAAS-basiertes Login

Abb. 2: Ablauf einer JAAS-Anwendung

Üblicherweise ist im Rahmen der Identifikation eines Benutzers eine Interaktion mit diesem notwendig. Dabei kann es sich um die Eingabe von Benutzernamen und Passwort handeln oder auch nur um die Aufforderung, einen Finger auf den Fingerabdruck-Scanner zu legen. Die Implementierung von Ein- und Ausgabe muss zur Realisierung einer einheitlichen Benutzerschnittstelle sinnvoller Weise durch die Anwendung erfolgen. Um der Anforderung nach Anwendungsunabhängigkeit gerecht zu werden, muss JAAS Mechanismen bereitstellen, die es erlauben, Benutzerinteraktionen außerhalb eines Login-Moduls zu implementieren, diese aber innerhalb der Module zu steuern. Der in JAAS beschrittene Weg hierfür heißt Callbacks. JAAS definiert für die Verwendung von Callbacks zwei Interfaces. Callback ist ein Tag-Interface ohne eigene Methoden. Klassen, die dieses Interface implementieren, stellen Objekte dar, die der Anwendung Informationen liefern, was für eine Interaktion benötigt wird. Darüber hinaus fungieren sie als Datenaustauschobjekt zwischen Anwendung und Login-Module. JAAS beinhaltet bereits Callbacks für verschiedene Zwecke. In Listing 2 werden NameCallback und PasswordCallback zur Ermittlung von Benutzernamen und Passwort verwendet. CallbackHandler werden von Anwendungen implementiert und durch Login-Module aufgerufen. Der zu verwendende CallbackHandler wird einem Login-Modul beim Aufruf der initialize-Methode bekannt gemacht.

Listing 2: Verwendung von Callbacks im Login-Modul

public class SampleAction implements PrivilegedAction
{
    public void run()
    {
        System.out.println( "Home directory: " +
            System.getProperty( "user.home" ) );
    }
}

Für den Betrieb einer JAAS-basierten Anwendung sind diverse Einstellungen durchzuführen, die in [1] und [3] ausführlich beschrieben werden. Die notwendigen Konfigurationen lassen sich in drei Bereiche unterteilen, die an unterschiedlichen Stellen im System durchzuführen sind: Allgemeine Konfigurationen, Login-Konfiguration und Policy-Konfiguration. Einstellungen zur allgemeinen Konfiguration werden in der Datei ($JRE_HOME)/lib/security/java.security vorgenommen. Hierzu gehört die Konfiguration von PolicyProvider und ConfigurationProvider. Dies sind Klassen, die für die Ermittlung und Bereitstellung von Zugriffsberechtigungen und Login-Konfiguration verantwortlich sind. JAAS stellt mit den Klassen PolicyFile und ConfigFile für beide Provider eine Default-Implementierung bereit. Beide Default-Implementierungen erwarten in java.security weitere Properties, mit denen die auszuwertenden Konfigurationsdateien spezifiziert werden [3]. Darüber hinaus ermöglichen beide Provider, durch die Spezifikation von System-Properties beim Aufruf der JVM, weitere Konfigurationsdateien zu spezifizieren.
Die Login-Konfiguration legt fest, welche Login-Module für einzelne Applikationen zu verwenden sind. Folgendes Listing zeigt ein Beispiel, in dem für die Anwendung SampleApplication zwei Module konfiguriert sind:

SampleApplication {
    de.frusty.auth.PasswordModule sufficient;
    de.frusty.auth.SmartCardModule required debug=true;
};

Die Flexibilität und Konfigurationsmöglichkeiten von JAAS bieten breiten Raum für diverse Angriffs-Szenarien. Prinzipiell können zwei Angriffstypen unterschieden werden: das Vortäuschen falscher Identitäten durch einen Angriff auf die Login-Module und das Erlangen zusätzlicher Berechtigungen. Ersteres lässt sich zum einen durch den physischen Austausch von Login-Modulen erreichen. Durch die Verwendung von JAAS wird ein solches Vorgehen jedoch nur unwesentlich durch die Verwendung standardisierter Schnittstellen erleichtert. Da die Schnittstelle der auszutauschenden Klasse genau bekannt ist, wird die Erstellung eines gefälschten Moduls vereinfacht. Der eigentliche Austausch der Klasse lässt sich jedoch mit den gleichen Mitteln bewerkstelligen, wie auch in herkömmlichen Anwendungen. Zum anderen ist JAAS so entworfen, dass der Austausch von Login-Modulen vereinfacht wird. Durch Veränderungen an der Login-Konfiguration kann auf einfachem Weg dafür gesorgt werden, dass zur Authentisierung eines Benutzers vollkommen andere Login-Module verwendet werden. Dies kann entweder durch Editieren einer bestehenden Konfiguration oder auch durch Spezifikation einer anderen Konfiguration auf dem Weg der System-Properties (-Djava.security.auth.login.config) erfolgen, diese Möglichkeit besteht in herkömmlich realisierten Anmeldeverfahren nicht. Ein ähnlicher Weg kann auch zur Erlangung zusätzlicher Rechte genutzt werden. Auch die Dateien, in welcher die Berechtigungen konfiguriert werden, können u.U. verändert werden. Der Weg, zusätzliche Dateien auf dem Weg der System-Properties zu spezifizieren, ist ebenfalls möglich. Berechtigungen, die in einer Anwendung programmatisch vergeben werden oder unter Kontrolle eines Backend-Systems (beispielsweise einer Datenbank) stehen, sind deutlich schwieriger zu umgehen.

Zur Vermeidung dieser Angriffsszenarien muss auf eine sichere Konfiguration der Systemumgebung größten Wert gelegt werden. So lassen sich Veränderungen der verwendeten Dateien durch entsprechende Dateizugriffsberechtigungen unterbinden. Durch Spezifikation der Property policy.allowSystemProperty=false in der Datei java.security lässt sich auch die Spezifikation anderer oder zusätzlicher Konfigurationsdateien auf der Kommandozeile unterbinden. Diese Maßnahmen führen jedoch nur dann zum gewünschten Ziel, wenn der Endbenutzer nicht die Berechtigung besitzt zusätzliche Software zu installieren. Besteht diese Berechtigung, dann ist ein Angreifer in der Lage ein weiteres Java-Runtime zu installieren, das seinen Bedürfnissen entsprechend konfiguriert ist. Bei Ausführung einer JAAS-Anwendung in einem solchen Java-Runtime bestehen wieder alle oben beschriebenen Angriffsmöglichkeiten. Letzteres Risiko besteht auch dadurch, dass häufig ohnehin schon mehrere Runtimes mit verschiedenen Anwendungen installiert sind. Dem kann nur dadurch Abhilfe geschaffen werden, dass ein Endbenutzer ausschließlich vordefinierte Programme starten kann. Das Ausführen von Programmen in einer Shell oder mit Start | Ausführen unter Windows muss in diesem Fall vollständig unterbunden werden.

  • [1] Sun Microsystems, JAAS Developer’s Guide, java.sun.com
  • [2] Sun Microsystems, JAAS Login Module Developer’s Guide, java.sun.com
  • [3] Sun Microsystems, JAAS API Documentation, java.sun.com
  • [4] Sun Microsystems, JAAS Frequently Asked Questions, java.sun.com/security/jaas/faq.html
  • [5] Sun Microsystems, Security Architecture Specification, Java2 SDK Documentation,
    java.sun.com
  • [6] Sun Microsystems, Permissions in the Java2 SDK, Java2 SDK Documentation,
    java.sun.com
  • [7] Lai, Charlie; Samar, Vipin; Sun Microsystems, Making Login Services
    Independant of Authentication Technologies, java.sun.com
  • [8] Lai; Gong; Koved; Nadalin; Schemers; User Authentication and Authorization
    in the Java (TM) Platform, Proceedings of the 15th Annual Computer Security Applications Conference, Dec. 1999
Geschrieben von
Wolfgang Korn
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.