Der Server schickt nur sein eigenes Zertifikat und lässt das Zwischenzertifikat weg. Browser holen es nach, Apps und Skripte tun das oft nicht.
Aufwand:
ca. 25 Min.
Voraussetzung:
OpenSSL auf der Kommandozeile, Zugriff auf die TLS-Konfiguration des Servers
Gilt für:
TLS 1.3 nach RFC 8446, Zertifikate nach RFC 5280
Das Symptom
Das neue Zertifikat ist eingespielt, die Seite lädt, das Schloss ist zu. Zwei
Tage später kommen die Meldungen: Die Android-App bekommt keine Verbindung mehr.
Der Zahlungsdienstleister meldet einen fehlgeschlagenen Rückruf. Ein Kollege
schickt einen Screenshot aus dem Terminal, in dem von einem unbekannten
Aussteller die Rede ist. Am eigenen Rechner ist im Browser weiterhin alles grün.
Das Zertifikat wird also erneut ausgestellt, dann der Cache geleert, dann der
Server neu gestartet. Nichts davon ändert etwas, weil nichts davon das Problem
berührt.
Die „Layer 8“-Wahrheit
Ein Serverzertifikat allein ist keine Kette. Es ist ein Glied, das auf ein
weiteres Glied zeigt, und erst dieses landet irgendwann bei einem
Vertrauensanker, den die Gegenseite bereits kennt. RFC 8446 Abschnitt 4.4.2
regelt für TLS 1.3, wie diese Glieder auf die Leitung gehören: Das eigene
Zertifikat des Absenders muss im ersten CertificateEntry stehen, und jedes
folgende Zertifikat soll das unmittelbar vorangehende direkt zertifizieren. Und
dann steht dort der Satz, den man in beide Richtungen lesen muss: Weil
Vertrauensanker unabhängig verteilt werden müssen, darf ein Zertifikat, das
einen Vertrauensanker angibt, aus der Kette weggelassen werden, sofern bekannt
ist, dass die unterstützten Gegenstellen die weggelassenen Zertifikate besitzen.
Weggelassen werden darf also die Wurzel. Nur die Wurzel. Das Zwischenzertifikat
ist kein Vertrauensanker, und es wohnt auch in keinem Betriebssystem.
Warum es im Browser trotzdem läuft, ist kein Zufall und keine Nachsicht, sondern
ein zweiter, ganz anderer Mechanismus. Zertifikate können nach RFC 5280
Abschnitt 4.2.2.1 eine Erweiterung „Authority Information Access“ tragen; mit
der Zugriffsmethode id-ad-caIssuers verweist sie auf Zertifikate, die an die
ausstellende CA ausgegeben wurden, und ihr in RFC 5280 beschriebener Zweck ist
es, Zertifikatsnutzern bei der Auswahl eines Pfads zu helfen, der bei einem
vertrauenswürdigen Punkt endet. Große Browser folgen diesem Verweis und holen
sich das fehlende Glied selbst. Ein Kommandozeilenwerkzeug, eine
Embedded-Bibliothek, ein Mobilfunk-Stack oder eine Sprachlaufzeit mit eigenem
TLS-Unterbau tun das in aller Regel nicht. Der Standard schreibt es niemandem
vor. Genau deshalb sortiert sich die Welt in dieser Fehlerklasse so sauber in
„Browser sagt ja“ und „alles andere sagt nein“ – und genau deshalb ist der
eigene Browser das denkbar schlechteste Prüfwerkzeug für die eigene Kette.
Die Diagnose ist erfreulich kurz, wenn man das richtige Werkzeug richtig liest.
Was der Server sendet, zeigt s_client mit -showcerts, und die OpenSSL-Manpage
stellt dazu ausdrücklich klar, dass diese Liste nur aus den vom Server
gesendeten Zertifikaten in der Reihenfolge des Servers besteht und keine
verifizierte Kette ist. Für diese eine Frage ist das perfekt: Es geht nicht um
die Bewertung, sondern darum, ob überhaupt mehr als ein Zertifikat ankommt.
Kommt nur eines und ist sein Aussteller keine bekannte Wurzel, ist der Fall
entschieden – ohne dass irgendein Vertrauensspeicher, irgendein Client oder
irgendein Cache daran beteiligt wäre. Die Reparatur besteht dann aus einer
Zertifikatsdatei in der richtigen Reihenfolge und aus dem Verzicht darauf, die
Wurzel mit anzuhängen. Sie hilft nichts. Sie darf nach RFC 8446 sogar fehlen.
Die echte, verifizierte Lösung
1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:
1.
Zählen, was tatsächlich über die Leitung kommt
Der ganze Fall entscheidet sich an einer Zahl. Mit -showcerts zeigt s_client die vom Server gesendete Liste in der Reihenfolge des Servers an; die Manpage betont, dass es sich dabei nicht um eine verifizierte Kette handelt. Genau das ist hier erwünscht, denn gefragt ist nicht die Bewertung, sondern der Rohbestand.
Ist nur ein Zertifikat angekommen, entscheidet sein Aussteller alles Weitere. Ist der Aussteller eine bekannte Wurzel, ist die Kette vollständig. Ist er eine Zwischenstelle, fehlt genau ein Glied – und zwar eines, das der Server nach RFC 8446 Abschnitt 4.4.2 hätte mitsenden sollen, weil dort nur Vertrauensanker weggelassen werden dürfen.
s_client setzt den Handshake nach Zertifikatsfehlern absichtlich fort und akzeptiert dabei laut Manpage jede gesendete Kette, vertrauenswürdig oder nicht. Erst -verify_return_error gibt Prüffehler zurück und bricht den Handshake typischerweise mit einem Fatal Error ab. Nur dieser Aufruf beantwortet die Frage, wie sich eine echte Anwendung verhalten wird.
Die Reihenfolge prüfen, nicht nur die Vollständigkeit
RFC 8446 Abschnitt 4.4.2 verlangt, dass das eigene Zertifikat des Absenders im ersten CertificateEntry steht, und empfiehlt, dass jedes folgende Zertifikat das unmittelbar vorangehende direkt zertifiziert. Die Anmerkung im selben Abschnitt rät Implementierungen zwar zur Nachsicht gegenüber überzähligen Zertifikaten und beliebigen Reihenfolgen – aber ausdrücklich mit der Ausnahme des Endeinrichtungszertifikats, das zuerst kommen muss. Wer auf Nachsicht baut, baut auf fremde Kulanz.
5.
Die Datei auf dem Server zusammensetzen, nicht die Wurzel anhängen
Die übliche Reparatur ist eine Zertifikatsdatei, die zuerst das Serverzertifikat und danach die Zwischenzertifikate enthält. Das Wurzelzertifikat gehört nicht dazu: RFC 8446 Abschnitt 4.4.2 erlaubt sein Weglassen ausdrücklich, weil Vertrauensanker unabhängig verteilt werden müssen – mitgeschickt kostet es nur Bytes und ersetzt keinen fehlenden Vertrauensspeicher auf der Gegenseite.
6.
Nicht auf das Nachladen durch den Client hoffen
Die Erweiterung Authority Information Access nach RFC 5280 Abschnitt 4.2.2.1 kann mit der Zugriffsmethode id-ad-caIssuers auf Zertifikate der ausstellenden CA verweisen; RFC 5280 beschreibt ihren Zweck als Hilfe bei der Auswahl eines Pfads, der bei einem vertrauenswürdigen Punkt endet. Das ist eine Angabe im Zertifikat, keine Pflicht des Clients, sie abzurufen. Eine Kette, die nur funktioniert, weil manche Clients nachladen, ist keine reparierte Kette, sondern eine, deren Fehler gerade niemand sieht.
Häufige Fragen (FAQ)
?Warum funktioniert es ausgerechnet im Browser?
Weil Browser eine Abkürzung nehmen, die andere Software nicht nimmt. Zertifikate können nach RFC 5280 Abschnitt 4.2.2.1 eine Erweiterung „Authority Information Access“ tragen. Steht dort die Zugriffsmethode id-ad-caIssuers, verweist sie laut RFC 5280 auf Zertifikate, die an die ausstellende CA ausgegeben wurden; der Zweck dieser Angabe ist es ausdrücklich, Zertifikatsnutzern bei der Auswahl eines Zertifizierungspfads zu helfen, der bei einem von ihnen als vertrauenswürdig eingestuften Punkt endet. Viele Browser laden das fehlende Zwischenzertifikat über diesen Verweis einfach nach. Der Standard verpflichtet niemanden dazu – deshalb tun es schlanke Bibliotheken, eingebettete Geräte und viele Kommandozeilenwerkzeuge nicht.
?Muss der Server denn alle Zertifikate mitschicken?
Alle bis auf eines. RFC 8446 Abschnitt 4.4.2 legt für TLS 1.3 fest: „The sender's certificate MUST come in the first CertificateEntry in the list. Each following certificate SHOULD directly certify the one immediately preceding it.“ Direkt danach kommt die Ausnahme, und sie betrifft nur die Wurzel: Weil Vertrauensanker unabhängig verteilt werden müssen, darf ein Zertifikat, das einen Vertrauensanker angibt, aus der Kette weggelassen werden, sofern bekannt ist, dass die unterstützten Gegenstellen die weggelassenen Zertifikate besitzen. Das Wurzelzertifikat darf also fehlen. Das Zwischenzertifikat ist damit nicht gemeint.
?Der Server schickt zwei Zwischenzertifikate. Ist das ein Fehler?
Nicht zwingend. RFC 8446 Abschnitt 4.4.2 hat dafür eine eigene Anmerkung: Vor TLS 1.3 verlangte die Reihenfolge der certificate_list, dass jedes Zertifikat das unmittelbar vorangehende zertifiziert, manche Implementierungen erlaubten aber Spielraum. Server senden mitunter ein aktuelles und ein abgekündigtes Zwischenzertifikat für Übergangszwecke, andere sind schlicht falsch konfiguriert, und beide Fälle lassen sich trotzdem korrekt validieren. Für maximale Kompatibilität sollen Implementierungen laut derselben Anmerkung auf überzählige Zertifikate und beliebige Reihenfolgen vorbereitet sein – mit der einen Ausnahme, dass das Endeinrichtungszertifikat zuerst kommen muss.
?Woran erkenne ich, ob der Server oder mein Rechner schuld ist?
An der Anzahl der gesendeten Zertifikate. Die Manpage zu openssl-s_client beschreibt -showcerts als Anzeige der Zertifikatsliste so, wie der Server sie gesendet hat, in der Reihenfolge des Servers, und stellt klar, dass dies keine verifizierte Kette ist. Genau deshalb taugt sie zur Abgrenzung: Kommt nur ein einziges Zertifikat an, obwohl der Aussteller keine bekannte Wurzel ist, fehlt die Zwischenstufe auf der Leitung – das ist ein Serverproblem. Kommen zwei oder mehr an und es scheitert trotzdem, liegt es eher am Vertrauensspeicher der eigenen Seite.
?Kann eine leere Zertifikatsliste vorkommen?
Vom Server nicht. RFC 8446 Abschnitt 4.4.2 hält fest: „The server's certificate_list MUST always be non-empty.“ Umgekehrt ist es erlaubt: Ein Client sendet eine leere certificate_list, wenn er auf die Authentifizierungsanfrage des Servers kein passendes Zertifikat anzubieten hat – und muss die Finished-Nachricht laut demselben Abschnitt trotzdem senden.
Belege
Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.
Liegen mehrere HTTPS-Namen auf einer IP, entscheidet die SNI-Erweiterung, welches Zertifikat kommt. Fehlt sie, liefert der Server das Standardzertifikat.
Der Browser meldet ERR_TOO_MANY_REDIRECTS und die Seite lädt nie fertig? Eine Weiterleitungsschleife ist schuld. So findest du sie auf Client und Server.