Die Nutzerauthentifizierung mittels Username und Passwort ist immer noch Standard bei der Entwicklung von Webanwendungen. Auch in vielen Web-Services-Umgebungen ist Authentifizierung nach wie vor ein Problem. Ein SSL-Client-Zertifikat mit einer Passphrase - am besten PIN-geschützt auf einer Smartcard - erhöht die Sicherheit der Authentifizierung und ermöglicht auch die sichere Nutzung von Anwendungen über das Internet. Basierend auf der Erfahrung aus mehreren Projekten zeigt dieser Artikel am Beispiel des Tomcat, wie einfach dieser Authentifizierungsmechanismus realisierbar ist - sowohl in neu entwickelten Anwendungen als auch als Erweiterung zu bereits bestehenden Projekten.
Zertifikate – warum und wofür
Gegenüber der überwiegend verwendeten Passwort-Authentifizierung bietet die Authentifizierung mit Client-Zertifikaten mehrere Vorteile:- Es gibt keine schwachen Passwörter mehr.
- Die Weitergabe der Login-Information wird erschwert.
- Mit einem Zertifikat kann der Zugang zu vielen Diensten ermöglicht werden (Single Sign-on).
- Diese Form der Authentifizierung lässt sich sehr gut auch auf andere Dienste wie z.B. Web Services übertragen.
Bei der Auswahl von Kartenlesern, Karten und Software für die Einbindung in den Browser ist es ratsam, alles aus einer Hand zu beziehen, um Kompatibilitätsprobleme zu vermeiden. Es gibt verschiedene Klassifikationen von Kartenlesern: Das Mindeste, was ein Kartenleser mitbringen muss, ist eine eigene Tastatur (oft als Kartenleser Klasse 2 bezeichnet), um ein Ausspähen der PIN durch Keylogger o.Ä. auszuschließen. Wird serverseitig ein erneutes Handshake gestartet (z.B. nach Ablauf der Session bei Inaktivität), so ist es nicht selbstverständlich, dass ein Benutzer zur erneuten PIN-Eingabe aufgefordert wird, solange der Browser nicht geschlossen wird. Dieses PIN-Caching birgt im nicht privaten Bereich Sicherheitsrisiken, falls der User den Arbeitsplatz verlässt und weder den Browser schließt noch die Karte aus dem Leser entfernt. Außerdem sollten Browser und Plattformunterstützung beim Hersteller erfragt werden.
Zertifikate – auch für Clients
Im Falle der Kommunikation über HTTPS weist sich das Serversystem gegenüber dem Nutzer mit einem Zertifikat aus. So kann der Nutzer sicher sein, mit dem entsprechenden System, z.B. der Bank, zu kommunizieren. Die Authentifizierung des Nutzers erfolgt dann aber meistens über den so gesicherten Kanal mittels Username und Passwort. Der Server kann auch vom Client verlangen, sich beim Verbindungsaufbau (SSL Handshake) ebenfalls mit einem Zertifikat auszuweisen. Dieses Zertifikat ist idealerweise auf einer Smartcard gespeichert und mit einer PIN geschützt und verlässt so niemals die Karte; vielmehr wird auf dem Kartenleser der SSL-Session-Key signiert.Zertifikate – die Praxis
Zum Entwickeln und Testen werden weder Kartenleser noch Smartcards benötigt: Beteiligt sind ein Browser mit SSL-Client-Zertifikat und ein Application Server (unsere Beispiele beziehen sich auf Tomcat in der Version 5.5.7). Die Umstellung auf den produktiven Einsatz (etwa mit Apache2/mod_ssl/mod_jk und tatsächlichen Kartenlesern) ist dann mit wenigen Handgriffen erledigt. Das Aufsetzen einer CA zu Entwicklungszwecken und die Erzeugung der Zertifikate sind im Textkasten beschrieben. Mit dem Import der CA- und Client-Zertifikate in den Browser ist auf Nutzerseite die Umstellung erledigt. Zum Testen mit mehreren Accounts ist es ratsam, im Browser die Option zu aktivieren, jedes Mal bei der SSL-Authentifizierung nachzufragen, welches Zertifikat vorgewiesen werden soll. Serverseitig müssen erst einmal der HTTPS Connector aktiviert und ein Server-Zertifikat erzeugt werden. Diese beiden Schritte sind in der server.xml des Tomcat und hier erklärt. Damit der Server ein Zertifikat vom Client verlangt, muss die Option clientAuth= " true " in der Tomcat-Konfiguration gesetzt werden, sodass die Konfiguration des SSL Connector wie in Listing 1 aussieht. Dann fragt Tomcat das Zertifikat ab.Listing 1<Connector port="8443"maxThreads="150" minSpareThreads="25" maxSpareThreads="75"enableLookups="false" disableUploadTimeout="true"acceptCount="100" scheme="https" secure="true"clientAuth="true" sslProtocol="TLS"keystoreFile="c:\tomcat.keystore" keystorePass="change_me"truststoreFile="c:\tomcat.keystore" truststorePass="change_me"/>
Programmatische vs. deklarative Sicherheit
Deklarative Sicherheit bedeutet, dass Authentifizierung und Autorisierung mit den im Application Server enthaltenen Mitteln gelöst und ausschließlich in Konfigurationsdateien eingestellt werden (Container Managed Security). Bei programmatischer Sicherheit hingegen übernimmt die Anwendung selbst diese Aufgaben. Beide Ansätze haben Vor- und Nachteile: Deklarative Sicherheit spart Code und regelt alles an einer Stelle. Eine Designentscheidung, die so oder so bewertet werden kann: Durch die typische Aufgabentrennung zwischen Entwickler und Administrator bzw. Hoster gibt der Entwickler die Kontrolle über die Authentifizierung und Autorisierung ab. Abhängig von den benutzten Features kann deklarative Sicherheit aber die Portierbarkeit einschränken und eine Anwendung auf einen Application Server oder eine bestimmte Version des Servers oder der Servlet-Spezifikation festlegen. Beide Ansätze können sich gut ergänzen. Tomcat kennt SSL-Client-Zertifikate als Authentifizirungsmechnismus; dieses Verfahren kann im Deployment Descriptor ( web.xml ) der Anwendung eingestellt werden:<login-config><auth-method>CLIENT-CERT</auth-method></login-config>
<user username="EMAILADDRESS=mustermann@tembit.de,CN=Markus Mustermann, O=Tembit, L=Berlin, S=Berlin,C=DE" password="null" roles="admin"/>
Serverseitige Zertifikatsextraktion und -analyse
In einem Servlet wird auf die Zertifikatsinformation wie in Listing 2 zugegriffen.Listing 2//get certificates from requestObject o = request.getAttribute("javax.servlet.request.X509Certificate");java.security.cert.X509Certificate clientcert = null;java.security.cert.X509Certificate[] certificates = null;if(o != null) {certificates = (java.security.cert.X509Certificate[]) o ;clientcert = certificates[0];} else { //error: no client cert in request }
- Distinguished Name (DN) des Inhabers: getSubjectDN()
- Seriennummer des Zertifikats: getSerial-Number()
- Gültigkeitszeitraum des Zertifikats: checkValidity()
- verschiedene Informationen zum Aussteller: getIssuerDN()
- öffentlicher Schlüssel bzw. Fingerprint: getSignature() Informationen zu den zulässigen Verwendungszwecken, Signaturalgorithmen und Protokollversionen des Zertifikats
Integration in die Anwendung
Wird eine bestehende Anwendung komplett auf die Authentifizierung mittels Zertifikaten umgestellt (gibt es keine User-Name-/Passwortabfrage mehr), so kann – wie bei deklarativer Sicherheit mit Realms – der SubjectDN den User-Namen ersetzen. Zusätzlich kann die SerialNumber als Passwort benutzt werden, um Probleme mit erneuerten und somit doppelt ausgestellten Zertifikaten für die gleiche Person zu umgehen. Die Datenstrukturen selbst und die Prüfung der Zugriffsrechte bleiben von dieser Änderung unberührt. Bei neuen Projekten sollte analog vorgegangen werden. Integriert werden kann die programmatische Zertifikatsprüfung an einer zentralen Stelle der Applikation. Dazu bieten sich verschiedene Möglichkeiten an:- Valve bzw. Filter: Für Code, der jeden Request behandelt, bietet Tomcat schon lange das Valve-Konzept. Ein Beispiel für eine spezielle SSLCertAccessValve wird im nächsten Abschnitt entwickelt. Ein Filter lässt sich analog implementieren.
- Ersetzen der User-Name/Passwort-Prüfung: Wurde in einer bestehenden Anwendung eine programmatische Login-Prozedur implementiert, so kann der Code an genau dieser Stelle ausgetauscht werden.
- zentrale Codestelle: Existieren Codestellen, die von jedem Request durchlaufen werden (wie etwa ein RequestProcessor im Struts-Framework), so kann der Zertifikatstest hier eingebaut werden.
- Ein manueller Aufruf entsprechender Prüfroutinen aus verschiedenen Stellen der Anwendung heraus ist zwar möglich, aber nicht empfehlenswert.
Grenzstation – eine AccessValve
Um eigene Valves komfortabel zu implementieren, bietet Tomcat mit org.apache.catalina.valves.ValveBase eine abstrakte Klasse, in der nur noch die Methode in voke(...) überschrieben werden muss:package com.tembit.example;//import declarationspublic class SSLCertAccessValve extends org.apache.catalina.valves.ValveBase {void invoke(Request request, Response response)throws java.io.IOException, javax.servlet.ServletException {//check certificate here}}
Web Services
Zum Schluss noch ein kurzer Exkurs zu Web Services mit Apache Axis. Serverseitig ist die Integration des Zertifikatcodes anhand von AccessValve ideal, da an bestehenden Web Services kein Code verändert bzw. in neuen Projekten kein Code eingefügt werden muss.Zum Entwickeln und Testen einer Smartcard-Anwendung kann die dafür benötigte CA durch das bei OpenSSL mitgelieferte Skript CA.pl simuliert werden. Die OpenSSL-Pakete für Linux/Unix finden sich unter www.openssl.org, für Windows empfiehlt sich die Binärdistribution von www.slproweb.com. Initialisierung und CA-Zertifikat Zur Erzeugung wird CA.pl -newca aufgerufen. Das Skript fragt die nötigen Daten ab und erzeugt ein selbst signiertes CA-Zertifikat. Server-Zertifikat für Tomcat Zunächst wird ein Keystore für den Server erzeugt, wobei zu beachten ist, dass der Common Name (CN) des Serverzertifikats auf den Servernamen (z.B. www.example.com ) ausgestellt wird:
keytool -genkey -keystore tomcat.keystore -alias mykey -storepass change_me -keyalg RSADamit Tomcat Client-Zertifikate validieren kann, muss der auch die TrustStore-Rolle übernehmen, dafür wird das CA-Zertifikat binär kodiert
openssl x509 -in demoCA\cacert.pem -outform DER -out CA-cert.cerund dann in den Keystore importiert:
keytool -keystore tomcat.keystore -storepass change_me -alias ca -import -file CA-cert.cerAnschließend wird ein Certificate Signing Request (CSR) erzeugt, von der CA signiert und wieder in den Keystore importiert:
keytool -certreq -keystore tomcat.keystore -storepass change_me -keyalg RSA -alias mykey -file newreq.pem CA.pl -signreq openssl x509 -in newcert.pem -outform DER -out newcert.cer keytool -keystore tomcat.keystore -storepass change_me -alias mykey -import -file newcert.cerNutzerzertifikate Nutzerzertifikate für Browser und Smartcards werden dann mit dem CA-Skript erzeugt und im PKCS#12- Format exportiert:
CA.pl -newreq CA.pl -signreq CA.pl -pkcs12
javax.net.ssl.keyStorejavax.net.ssl.keyStorePasswordjavax.net.ssl.trustStorejavax.net.ssl.trustStorePassword
Produktives System
Sowohl aus Performance- als auch aus Sicherheitsgründen empfiehlt es sich für den produktiven Einsatz, einen umfassend auditierten und erprobten Webserver wie z.B. Apache2 mit mod_ssl als Frontend vor dem Application Server zu betreiben. Die beiden Server werden dann über das Protokoll AJP verbunden. Das dazu eingesetzte mod_jk muss die Zertifikatsdaten von mod_ssl an den Application Server weiterreichen; das neuere mod_jk2 verursacht an dieser Stelle noch Probleme. CA-Zertifikat und Server-Zertifikat werden Apache-typisch an den entsprechenden Stellen installiert. Für den Export der Daten und das Abfragen des Client-Zertifikats werden in der Datei httpd.conf (oder je nach Distribution auch ssl.conf ) des Apache diese Zeilen eingefügt:SSLOptions +ExportCertData +StdEnvVars +CompatEnvVarsSSLVerifyClient require
JkExtractSSL OnJkHTTPSIndicator HTTPSJkSESSIONIndicator SSL_SESSION_IDJkCIPHERIndicator SSL_CIPHERJkCERTSIndicator SSL_CLIENT_CERT
Fazit
Eine Smartcard-Lösung zur Authentifizierung ist nicht nur sehr sicher, sondern auch besonders eingängig für die Nutzer. In Situationen, in denen ein solcher Ansatz Sinn macht, muss eigentlich nur ein Betreiber für die CA gefunden werden – entweder firmenintern oder als externer Dienstleister. Die eigentliche Implementierung in der Anwendung und dem Application Server ist – wie gezeigt – recht einfach; viele Vorurteile und Befürchtungen sind nicht berechtigt. Es wäre wünschenswert, dass mehr Entwickler diese Technologien in ihren Projekten anbieten und einsetzen.
Literatur
- Peter Roßbach, Lars Röwekamp: Ein Königreich für Tomcat. Tomcat 4 Security Realms, Java Magazin 11.2003
Broder Schümann (broder@unixmafia.de) arbeitet freiberuflich als Spezialist für Sicherheits- und Netzwerktechnik im Java-/Linux-/Unix-/Open-Source-Umfeld.
Das Material für diesen Artikel entstand hauptsächlich während der Zusammenarbeit der Autoren im GENOMatch-Projekt von Schering.




