PKI-loses TLS

Florian Weimer

Die einzig halbwegs funktionierende public key infrastructure (PKI) ist die, die in die Web-Browser eingebaut ist. Dies führte dazu, daß das verwendete kryptographische Protokoll TLS (eher unter dem Namen „SSL“ des Vorgängers bekannt) besonders ausgereift ist. Dessen Einsatz wird aber in anderem Kontext dadurch erschwert, daß es an eine PKI gebunden ist, deren Betrieb sehr aufwendig ist. Diese Notiz soll zeigen, wie TLS auch ohne PKI eingesetzt werden kann.

Warum keine PKI?

Der gängige Weg zum Einsatz von TLS besteht selbstverständlich darin, die benötigte PKI aufzusetzen. Im wesentlichen läuft dies auf den Betrieb einer Zertifizierungsinstanz (certification authority, CA) hinaus, die in kleinerem Maßstab das macht, was in der Welt der Browser-PKI die großen CAs machen: Zertifikatanforderungen nach vorgegebenen Kriterien prüfen und mit dem CA-Schlüssel signieren. Das ganze ist aufwendig, weil die typischerweise verfügbare Software für den CA-Betrieb schwer zu bedienen ist – und weil der CA-Schlüssel ziemliche Macht in sich trägt und damit besonders gesichert werden muß.

Das allein wäre nicht so schlimm, würde das Vorhandensein einer CA (abgesehen von der Möglichkeit, TLS zu verwenden) weitere Vorteile bieten würde. Dies ist aber offenbar nicht der Fall, denn Benutzer- und Rechteverwaltung und Konfiguration der Anwendungen wird durch sie nicht wesentlich erleichtert:

(Wir nehmen hier und im folgenden eine Architektur an, die im wesentlichen dem Client-Server-Paradigma folgt, einfach weil dies die einzige ist, für die praktikable und bewährte Sicherheitsmodelle vorhanden sind.)

Damit sind auf beiden Seiten Konfigurationsarbeiten (bzw. Softwareinstallation erforderlich). Das Ziel, lediglich ein Zertifikat zu erzeugen, womit der Inhaber alle benötigten Dienste nutzen kann, ist so nicht zu erreichen. Und wenn der Administrator sowieso benutzerspezifische Daten einpflegen muß, kann er auch gleich einen kryptographischen Schlüssel eintragen.

Meine Schlußfolgerung daraus ist, daß man sich den Aufwand des Betriebs einer CA möglichst ersparen sollte, weil eine PKI im täglichen Betrieb den Arbeitsaufwand nicht reduziert.

Vorab ausgetauschte Geheimnisse

RFC 4279 <http://www.rfc-editor.org/rfc/rfc4279.txt> beschreibt eine Möglichkeit, wie man mit vorab ausgetauschten Geheimnissen (pre-shared keys) TLS betreiben kann und auf diese Weise die Abhängigkeit von einer PKI verliert. Auf den ersten Blick leistet das genau das gesuchte.

Die Unterstützung von pre-shared keys ist allerdings sehr dürftig. In OpenSSL ist Nokias Implementierung schon seit über einem Jahr im CVS enthalten ist, aber sie wohl erst mit Version 0.9.9 offiziell freigegeben werden. Von den verbreiteten Implementierungen unterstützt nur GNUTLS diese Erweiterung.

Die Authentifizierung mittels symmetrischer Verschlüsselung weist zudem den Nachteil auf, daß man pro Pärchen aus Client und Server einen Schlüssel braucht. Wie wir oben gesehen haben, ist das auf der Server-Seite kein Problem, weil sowieso Client-spezifische Konfiguration erforderlich ist. Auf der Client-Seite reduziert es aber den Verwaltungsaufwand, wenn man nur ein Geheimnis für alle genutzten Server nutzen müßte.

Ein Ansatz mit einer von allen vertrauten Partei (à la Kerberos) wäre möglich, führt aber ein sehr zentralen Dienst ein, der keinesfalls ausfallen bzw. aufgrund von Netzproblemen unerreichbar sein sollte. Firewall-Regeln werden ebenfalls komplizierter.

Selbstsignierte Zertifikate

In der Praxis ist es daher sinnvoller, bei Clients und Servern auf selbstsignierte Zertifikate zu setzen. Die Zertifikate sind dabei strenggenommen nur Beiwerk (auch wenn es sicherlich sinnvoll ist, im Common Name-Feld einen sprechenden, eindeutigen Namen einzutragen), die den Einsatz der rohen Schlüssel mit gängigen TLS-Implementierungen ermöglichen. (Es gibt Gerüchte, daß eine verbreitete TLS-Implementierung keine selbstsignierten Client-Zertifikate unterstützt; das wird sich demnächst herausstellen.)

Falls die Implementierung hinreichend flexibel ist, ist es auch möglich, lediglich gegen das Schlüsselmaterial zu authentifizieren. Dies birgt aber das Risiko, daß in der Definition der Äquivalenz des Schlüsselmaterials ein Fehler vorliegt, so daß man z.B. mit einem anderen RSA-Exponenten (aber dem erwarteten Modul) einen Teilnehmer nachahmen kann. Die Zertifikate enthalten auch eine zufällige Komponente, so daß selbst bei einem schwerwiegend Fehler in der kryptographischen Implementierung, die de facto zu einem Wegfall der kryptographischen Bindung der Sitzung an ein Zertifikat führt, eine Anmeldung als Hinz und Kunz nicht ohne weiteres möglich ist. Dies gilt natürlich nur, falls die Zertifikate nicht sowieso in einem frei zugänglichen Verzeichnis stehen, und ist daher nur eine minimale zusätzliche Sicherung, die zumindest Wurm-basierte Angriffe erschweren sollte.

Wenn man diesen Ansatz verfolgt, kann man einfach die Server-Schlüssel zusammen mit der voreingestellten Konfiguration der Anwendungen an die Clients ausliefern. Die Client-Schlüssel werden zusammen mit den zugeteilten Rechten in die Authenfizierungsdatenbank des jeweiligen Servers eingetragen. (In Zeiten von SQLite <http://www.sqlite.org/> ist es kein Problem, dafür eine Datenbank einzusetzen. Dem berechtigten Einwand, Zertifikate seien gegenüber distinguished names unhandlich, kann man auch über den Einsatz von Hashes wie SHA-1 begegnen, allerdings erschwert dies die Fehlerdiagnose.)

Planmäßiger Schlüsselwechsel

Wenn, wie beschrieben, die Schlüssel der Server hartkodiert in den Client-Anwendungen enthalten sind, mag ein Schlüsselwechsel abenteuerlich erscheinen. Wie praktikabel dieser Ansatz ist, hängt stark davon ab, ob man eine funktionierende Softwareverteilung hat.

Demnächst werde ich Gelegenheit bekommen, den serverseitigen Schlüsselwechsel durchspielen zu können – glücklicherweise ohne Kompromittierung. Es stellte sich heraus, daß eine Middleware, die PKI-loses TLS als Transport verwendet, syntaktisch ungültige X.509-Zertifikate erzeugt. (Für Details siehe dieses Posting <http://lists.gnu.org/archive/html/help-gnutls/2007-03/msg00009.html> auf der GNUTLS-Mailingliste.) Dieser Fehler muß möglichst bald korrigiert werden, bevor nicht noch mehr Clients aufgesetzt wurden. Die größte Hürde ist, daß alle Clients gleichzeitig aktualisiert werden müssen. Noch ist die Zahl glücklicherweise sehr überschaubar, trotzdem ist dafür einiges an Planung erforderlich. Bei größeren Installationen ist dies natürlich nicht praktikabel durchführbar. Das Ausrollen des neuen Schlüssels ist an sich unproblematisch, da ein einfaches Software-Update dafür ausreicht und Infrastruktur für Software-Verteilung vorhanden ist.

Die wesentliche Hürde ist somit die erzwungene Gleichzeitigkeit der Aktualisierung der Clients. Deswegen überlege ich, bei der Middleware vor der TLS-Initialisierung einen Schritt einzubauen, in dem der Client einen Hinweis darauf schickt, welches Server-Zertifikat er erwartet (z.B. einen Hash über die DER-Kodierung). Auf diese Weise kann der Server jeweils das von der Client-Anwendung erwartete Zertifikat liefern. Das löst auch das Problem des virtuellen Hostings, und wenn man mehr als bloß einen Verweis auf das erwartete Server-Zertifikat mitschickt, kann man auf diese Weise auch Protokoll-Wechsel unterstützen.

RFC 3546 <http://www.rfc-editor.org/rfc/rfc3546.txt> beschreibt übrigens eine TLS-Erweiterung (server_name), mit der sich dies ebenfalls erreichen ließe, aber sie krankt am selben Problem wie pre-shared keys: Es gibt dafür im Feld kaum Unterstützung, zum Beispiel nicht in OpenSSL 0.9.8.

Auf Client-Seite taucht das Problem nicht auf, da TLS mit Client-Zertifikaten von vorneherein darauf ausgelegt ist, viele verschiedene Clients durch einen Server zu unterstützen.

Erzwungener Schlüsselrückruf

Bei kryptographischen Verfahren, deren Sicherheit auf der langfristigen Geheimhaltung von Daten besteht, stellt sich schnell die Frage, was zu tun ist, wenn die Geheimhaltung nicht mehr gewährleistet werden kann. (Dazu gesellen sich Probleme wie schludrige Prüfung durch CAs, die ebenfalls in einen Schlüsselrückruf münden können.) Das Schlüsselmaterial, das unseren selbstsignierten Zertifikaten zugrundeliegt, ist davon ebenfalls betroffen.

Die Praxis sagt ganz klar: Diese Nuß ist zu knifflig, ignoriere das Problem. Die Browser-PKI besitzt beispielsweise de facto keine Möglichkeit zum Schlüsselrückruf. Zwar gibt es Rückruflisten der CAs oder OCSP (RFC 2560 <http://www.rfc-editor.org/rfc/rfc2560.txt>), aber zugehörigen Server werden von CAs mit niedriger Priorität betrieben und sind häufig nicht erreichbar. Es gibt für Webserverbetreiber auch wenige Anreize, nach einer Kompromittierung das Zertifikat offiziell zurückzuziehen (anstatt es bloß nicht mehr einzusetzen – wenn man überhaupt willens ist, die Kosten für ein neues Zertifikat zu zahlen).

Wem das nicht genug ist, der möge sich überlegen, was er im Falle der Kompromittierung unternehmen muß: Die betroffene Einheit muß isoliert werden, und man wird, wenn man seine Nutzer ernst nimmt, um eine Benachrichtigung kaum herumkommen, die sowieso Handarbeit nachsichzieht. Auf der anderen Seite gibt es, unabhängig von den Schlüssel, häufig auch Bedarf, aus anderen Gründen Rechte zurückzuziehen (man erinnere sich daran, wie manche Unternehmen ihren Mitarbeitern kündigen). Dafür benötigt man eine möglichst einfache Möglichkeit, die auf den Servern eingetragenen Rechte wieder zu entfernen, was man auch zum Schlüsselrückruf nutzen kann.

Revisions


Florian Weimer
Home Blog (DE) Blog (EN) Impressum RSS Feeds