Certificate Pinning mit NGINX

Dieser Artikel beschreibt, was Certificate Pinning ist, wie es TLS/SSL-Verbindungen sicherer macht und wie man es für den Webserver NGINX konfiguriert.

Der Artikel steht in einer PDF-Version zum Download und Druck zur Verfügung: Certificate_Pinning_mit_NGINX

Einleitung

Um zu verstehen, wie Certificate Pinning hilft, TLS/SSL-Verbindungen sicherer zu machen, muss man sich zuerst der Schwachstelle der TLS/SSL-Verschlüsselung bewusst sein.

TLS/SSL-Verbindungen sollen die vertrauliche Kommunikation zwischen zwei Kommunikationspartnern sicherstellen. Bei den Kommunikationspartnern handelt es sich typischerweise um einen Client und einen Server. Die Sicherheit der Vertraulichkeit beruht darauf, dass der Client auch tatsächlich mit dem richtigen Server verbunden ist. Dazu weist sich der Server mit einem Zertifikat aus, welches von einer Zertifizierungsstelle (Certificate Authority, CA) ausgestellt wurde. Die Zertifizierungsstelle prüft die Identität des Dienstbetreibers und beglaubigt mit ihrer digitalen Signatur das Zertifikat.

Die c’t schreibt in ihrem Artikel „Festgenagelte Zertifikate“ in Ausgabe Nr. 23 vom 17.10.2015: „Das Problem dabei: Es gibt weit über hundert solcher Zertifizierungsstellen, denen die gängigen Internet-Programme wie Browser und E-Mail-Client vertrauen. Als wäre das nicht unübersichtlich genug, haben die dann auch noch zahllose Unter-CAs, die berechtigt und in der Lage sind, im Namen dieser CAs zu unterschreiben.“1

Das Problem besteht nun nicht in der Anzahl der Zertifizierungsstellen, sondern darin, dass jede dieser Zertifizierungsstellen Zertifikate für beliebige Domains ausstellen darf. So können sich Dritte ein Zertifikat auf eine bereits existierende Domain ausstellen lassen und dieses zum Beispiel für einen Man-In-The-Middle-Angriff (MITM-Angriff) verwenden.

Das genannte Angriffsszenario existiert nicht nur in der Theorie. Wie die c’t berichtet nutzte die chinesische Regierung gefälschte Google-Zertifikate auf ihrer großen Firewall, um den Google-Mail-Verkehr ihrer Bevölkerung überwachen zu können. Darüber hinaus werden weitere Fälle wie der Hack der niederländischen Zertifizierungsstelle DigiNotar und TrustWave aufgeführt.2 Im ersten Fall wurden gefälschte Zertifikate für GMail und Facebook ausgestellt. Im zweiten Fall wurden Zertifikate für Firmen ausgestellt, welche diese Zertifikate nutzten, um den verschlüsselten Internet-Verkehr ihrer Mitarbeiter zu überwachen.

Die Man-In-The-Middle-Angriffe funktionieren, da die Zertifizierungsstellen, welche die gefälschten Zertifikate ausgestellt haben, in der Liste der vertrauenswürdigen Zertifizierungsstellen der gängigen Browser geführt werden. Für den Browser ist damit auch das gefälschte Zertifikat gültig. Der Benutzer kann den MITM-Angriff nicht erkennen und nimmt fälschlicherweise an direkt mit dem gewünschten Server zu kommunizieren.

Um einen MITM-Angriff erkennen zu können, muss der Client überprüfen können, ob das ihm vorliegende Zertifikat von der CA des Dienstbetreibers oder von einer anderen CA ausgestellt wurde. Hier kommt Certificate Pinning ins Spiel.

Certificate Pinning für TLS/SSL

Certificate Pinning wurde im RFC 7469 spezifiziert.3 Es handelt sich dabei um einen Mechanismus, bestimmte Eigenschaften eines Zertifikats festzunageln. Der Browser erhält dabei mit dem Zertifikat zusätzliche Informationen, mit denen er die Authentizität des Zertifikats überprüfen kann.

In der Praxis wird dem Browser ein Hash-Wert übermittelt, welcher über den öffentlichen Schlüssel des Zertifikats gebildet wurde. Dieser Hash-Wert wird in einem HTTP-Header-Field an den Browser übertragen und von diesem gespeichert. Wie dieses Verfahren genau funktioniert, beschreibt der RFC 7469 ab Abschnitt 2.1.14 Da nur der Dienstbetreiber über den dazugehörigen privaten Schlüssel verfügt, ist ein Missbrauch durch Dritte ausgeschlossen. Übermittelt nun nämlich ein Angreifer bei einem MITM-Angriff den zu seinem Zertifikat gehörenden öffentlichen Schlüssel, kann der Browser mit Hilfe des PINs erkennen, dass dieser Schlüssel nicht dem Dienstbetreiber gehört und den Angriff damit auffliegen lassen.

Eine Schwachstelle bleibt jedoch. Damit das beschriebene Verfahren funktioniert, muss die erste Verbindung, die ein Client zum Server aufbaut, integer und vertrauenswürdig sein. Findet bereits beim ersten Verbindungsaufbau ein MITM-Angriff statt, kann der Angreifer einen zu seinem öffentlichen Schlüssel passenden Hash übermitteln und das beschriebene Verfahren damit aushebeln.

Es existiert also ein gewisses Henne-Ei-Problem, welches im folgenden Abschnitt kurz angerissen wird.

TOFU: Trust On First Use

Nein, mit TOFU ist an dieser Stelle kein Nahrungsmittel gemeint. TOFU steht in diesem Kontext für das Trust-On-First-Use-Prinzip, welches die c’t in ihrem Artikel „Zertifikate festnageln“ erläutert.5

Das darin beschriebene Henne-Ei-Problem besteht darin, dass man zuerst eine sichere Verbindung benötigt, um die erforderlichen Informationen zu erhalten, mit denen zukünftige Verbindungen gesichert werden können.

Mittlerweile sollte jedoch bekannt sein, dass es keine hundertprozentige Sicherheit gibt. Damit ist der beschriebene Schutz besser als gar keiner. In der Praxis kann Certificate Pinning daher in sehr vielen Fällen helfen, die Sicherheit vertraulicher Kommunikation zu steigern.

Certificate Pinning auf dem eigenen Server

Dieser Abschnitt beschreibt, wie man Certificate Pinning auf dem eigenen Server konfigurieren kann. Es wird dabei auf notwendige Vorüberlegungen eingegangen und die Berechnung der PINs beschrieben. Im Anschluss wird das Certificate Pinning beispielhaft an einem NGINX-Server demonstriert.

Vorüberlegungen

In den vorangegangenen Abschnitten wurde erläutert, wie Man-In-The-Middle-Angriffe durch Certificate Pinning erheblich erschwert werden können. Nun stellt sich die Frage, welchen öffentlichen Schlüssel man festnageln möchte. Denn Certificate Pinning kann auf jeden öffentlichen Schlüssel der gesamten Zertifizierungskette angewendet werden. So kommen sowohl das eigene Serverzertifikat, als auch das der Intermediate CAs und das der Root CA in Frage.6

Pinnt man den öffentlichen Schlüssel einer Intermediate CA oder gar einer Root CA, so werden alle von diesen Zertifizierungsstellen ausgestellten Zertifikate vom Browser als gültig und sicher akzeptiert. Daher erscheint es am sichersten, wenn man den öffentlichen Schlüssel des eigenen Serverzertifikats festnagelt. Hierbei muss allerdings folgendes Risiko beachtet werden.

Wird der Schlüssel durch Kompromittierung unbrauchbar, oder geht durch Hardwaredefekt verloren, können Benutzer die gesicherten Dienste eventuell nicht mehr nutzen. Denn die Browser haben den Pin gespeichert und werden vor Ablauf der Lebensdauer keinen neuen Pin akzeptieren. Die Lebensdauer kann je nach Konfiguration mehrere Wochen bis Monate betragen.7

Um das im vorigen Absatz beschriebene Risiko zu minimieren definiert RFC 7469 die zusätzliche Verwendung eines Backup-PINs. Dabei wird ein Hash-Wert über den öffentlichen Schlüssel eines Schlüsselpaares gebildet, welches aktuell noch nicht genutzt wird.8 Dies kann zum Beispiel dadurch erreicht werden, dass ein Hash-Wert für den öffentlichen Schlüssel eines Certificate Signing Request (CSR) generiert wird.

Der Backup-Pin wird ebenfalls über ein HTTP-Header-Feld ausgeliefert und vom Browser eines Clients gespeichert. Der erzeugte Backup-CSR sollte sicher offline aufbewahrt werden. Er kann genutzt werden, um ein neues Zertifikat für die entsprechende Domain ausstellen zu lassen. Auf diese Weise können Zertifikate verlängert bzw. erneuert werden, ohne dass der Zugriff auf die entsprechende Domain unterbrochen wird.

Backupstrategie

In diesem Abschnitt wird eine konkrete Backupstrategie für den Backup-Pin beschrieben.

Der für den Backup-Pin verwendete CSR ist sicher aufzubewahren. Denn mit ihm kann ein Zertifikat für eine Domain bzw. einen Host ausgestellt werden, welches von Clients als gültig anerkannt wird, da sie den dazugehörigen Backup-Pin gespeichert haben.

Ich persönlich speichere den CSR und den dazugehörigen privaten Schlüssel in KeePassX9. Auf diese Weise werden die Informationen sicher in einer Datenbank mit einer 256 Bit AES-Verschlüsselung abgelegt. Die KeePassX-Datenbank selbst bewahre ich in einem TeamDrive10-Space auf. Dadurch wird die Datenbank sicher auf meine Endgeräte synchronisiert, so dass die Daten auch bei Ausfall eines Endgeräts erhalten bleiben.

Die lokalen Datenträger der zur TeamDrive-Synchronisation verwendeten Endgeräte sind ebenfalls verschlüsselt. So sind die Daten im Falle eines Diebstahls eines Endgeräts gleich doppelt geschützt. Erstens durch die Verschlüsselung des lokalen Datenträgers und zweitens durch die verschlüsselte KeePassX-Datenbank.

Die PINs berechnen

Die benötigten PINs werden auf der Kommandozeile mit openssl generiert.11 Für ein existierendes SSL-Zertifikat kann der Pin mit folgendem Code erzeugt werden:

openssl x509 -noout -in certificate.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key
openssl dgst -sha256 -binary public.key | openssl enc -base64

Der erzeugte Pin wird auf der Standardausgabe ausgegeben und endet immer auf das Zeichen „=“.

Für den Backup-Pin wird zunächst ein neuer Certificate Signing Request erstellt:

openssl genrsa -out example.com.key 2048
openssl req -new -key example.com.key -out example.com.csr

Über den so erzeugten Certificate Signing Request (example.com.csr) wird nun ebenfalls ein Pin mit folgendem Code erzeugt:

openssl req -noout -in example.com.csr -pubkey | openssl asn1parse -noout -inform pem -out example.com_csr.key
openssl dgst -sha256 -binary example.com_csr.key | openssl enc -base64

Der erzeugte Backup-Pin wird ebenfalls auf der Standardausgabe ausgegeben und muss ebenfalls auf das Zeichen „=“ enden.

Konfiguration von NGINX

Sind die PINs erzeugt, kann anschließend der Webserver konfiguriert werden, diese auszuliefern. Neben der Pin-Direktive12 ist hier die Max-Age-Direktive13 von Bedeutung. Letztere gibt die Zeit in Sekunden an, für die ein Pin durch den Browser gespeichert wird.

Für die ersten Tests sollte die Max-Age-Direktive auf wenige Minuten gesetzt werden. Dieser Wert sollte erst bei reibungslosem Betrieb auf mehrere Wochen erhöht werden.

Das zusätzliche Header-Feld muss im SSL-Block der NGINX-Konfiguration hinzugefügt werden. Dazu wird folgender Code in den SSL-Block eingefügt:

add_header Public-Key-Pins 'pin-sha256="PRIMARY-PIN"; pin-sha256="BACKUP-PIN"; max-age=300; includeSubDomains';

Dabei sind PRIMARY-PIN und BACKUP-PIN durch die entsprechenden PINs zu ersetzen. Die optionale includeSubDomains-Direktive14 gibt an, dass die übermittelten PINs auch für alle Subdomains des Hosts gelten.

Anschließend muss die Konfiguration neue geladen werden, um diese zu aktivieren:

sudo service nginx reload

Fazit

Certificate Pinning ist ein in RFC 7469 spezifizierter Standard, welcher heute bereits von den weit verbreiteten Browsern Chrome und Firefox unterstützt wird. Auch die Konfiguration weit verbreiteter Webserver wie Apache, lighttpd und NGINX ist mit geringem Aufwand, wie hier am Beispiel von NGINX gezeigt, zu erledigen.

Lediglich die sichere Aufbewahrung des Backup-CSR ist sicherzustellen, um eine längere Nichterreichbarkeit einer Domain vermeiden zu können.

Damit ist Certificate Pinning grundsätzlich geeignet, die verschlüsselte Kommunikation im Internet noch sicherer zu machen.

Quellen:

  1. Schmidt, Jürgen: Festgenagelte Zertifikate: TLS wird sicherer durch Certificate Pinning, in: c’t magazin für computer technik, Nr. 23, 17.10.2015, S. 118, Spalte 2-3.
  2. Schmidt, Jürgen: Festgenagelte Zertifikate: TLS wird sicherer durch Certificate Pinning, in: c’t magazin für computer technik, Nr. 23, 17.10.2015, S. 119, Spalte 1.
  3. RFC 7469: Public Key Pinning Extension for HTTP
  4. RFC 7469 Section 2.1. Response Header Field Syntax
  5. Schmidt, Jürgen: Festgenagelte Zertifikate: TLS wird sicherer durch Certificate Pinning, in: c’t magazin für computer technik, Nr. 23, 17.10.2015, S. 121, Kasten „TOFU: Trust On First Use.
  6. Schmidt, Jürgen: Sicher mit Pin: Zertifikats-Pinning auf dem eigenen Server, in: c’t magazin für computer technik, Nr. 23, 17.10.2015, S. 122, Spalte 1.
  7. Schmidt, Jürgen: Sicher mit Pin: Zertifikats-Pinning auf dem eigenen Server, in: c’t magazin für computer technik, Nr. 23, 17.10.2015, S. 122, Spalte 2.
  8. RFC 7469, Abschnitt 4.3. Backup Pins
  9. The Official KeePassX Homepage
  10. TeamDrive Homepage
  11. RFC 7469: Appendix A. Fingerprint Generation
  12. RFC 7469: Abschnitt 2.1.1. The Pin Directive
  13. RFC 7469: Abschnitt 2.1.2. The max-age Directive
  14. RFC 7469: Abschnitt 2.1.3. The includeSubDomains Directive

6 Gedanken zu „Certificate Pinning mit NGINX

  1. Pingback: Pinning-Test im Firefox bei lokaler Root-CA erzwingen | My-IT-Brain

  2. Pingback: Erster bekannter Missbrauch eines Let’s Encrypt Zertifikats | My-IT-Brain

  3. Horst Weber

    Super Artikel zum Webserver NGINX und einem SSL/TLS Setup. Wird weiter empfohlen. !

    Die PDF Fassung ist super und man versteht sehr leicht um was es geht! Vielen Da nk für deine Arbeit!!!

    Antworten
  4. Pingback: Über Pinning (HPKP), CAA und Certificate Transparency | My-IT-Brain

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.