Donnerstag, 22 Februar, 2018

Mit HPKP unterstützen moderne Browser eine neuere Technik, um sich und seine Besucher vor falschen aber validen Zertifikaten zu schützen. In der jüngeren Vergangenheit hat es sich gezeigt, das kriminelle Firmen und Organisationen sich valide Zertifikate für bestimmte Domains ausstellen lassen und damit seinen Opfern vorgaukeln können, dass deren Verbindung vertrauenswürdig und abgesichert sei. In Wirklichkeit, wird aber der komplette Datenverkehr abgeschnorchelt (MitM) und ein Opfer hat nur wenige Möglichkeit das zu bemerken. Obwohl der Einsatz von HPKP sehr sinnvoll ist, haben nur ein paar tausend Webseiten die Technik im Einsatz - das ist schlicht ein Witz. Warum ist das so, ist der Einsatz wirklich so kompliziert und was kann schief laufen ?


Wie HPKP funktioniert

Mit dem Public Key Pinning wird, wie der Name schon andeutet, ein Schlüssel öffentlich gemacht. Es handelt sich dabei nicht um ein neues Zertifikat oder ähnlichem, sondern es wird vom verwendeten öffentlichem Zertifikat (CRT) lediglich ein Hash (Prüfsumme) erzeugt und vom Webserver bei jeder ausgelieferten Seite im Header eingefügt. Der Browser merkt sich nach dem ersten Besuch den Hash. Sollte sich in einem bestimmten Zeitraum das Zertifikat oder der Hash ändern, wird der Browser die Verbindung ablehnen.

Für den Einsatz des HPKP wird, laut RFC 7469, mindestens zwei Hashs benötigt. Der zweite Hash wird von einem sogenannten Backup-Zertifikat erzeugt. Der Hash des Backup-Zertifikats wird von einem neu erzeugtem Zertifikatsrequest (CSR) oder Zertifikat erstellt und sollte keines Falles von einem schon bestehendem/eingesetztem Zertifikatsschlüssel (KEY) erstellt werden. Das Backup-Zertifikat und auch dessen Zertifikatsschlüssel sollte nicht auf einem der genutzten Server liegen, sondern gesondert und gesichert abgelegt werden.

Die Hashes werden nun im Webserver hinterlegt, ausgeliefert und vom Browser beim ersten Besuch gespeichert. Sollte nun der Server kompromittiert werden, oder das Zertifikat wegen einem Fehler sein Vertrauen verloren haben, kann mit dem Backup ein neues Zertifikat erstellt werden bzw. das Backup-Zertifikat eingespielt und so eine neue valide Vertrauensstellung eingeführt werden. Danach ist das Backup-Zertifikat das neue valide und aktive Zertifikat und man benötigt wieder ein neues Backup-Zertifikat.


Worauf geachtet werden muss

Der Einsatz von HPKP ist nicht ganz unproblematisch, da die Besucher bei einer fehlerhaften Implementierung die Seite(n) für einen selbst bestimmten Zeitraum nicht mehr erreichen können. Zu dem muss der erste Kontakt vertrauenswürdig erfolgen, erst dann kann dem Mechanismus HPKP wirklich vertraut werden. Der erste Kontakt sollte z.B. mit DNSSec zusätzlich gesichert sein.

Es ist für den Administrator eine zusätzliche Verantwortung den Wechsel zu einem neuen Zertifikat frühzeitig mit einem weiteren Hash anzukündigen. Die Vertrauensstellung ist nach dem Besuch zeitlich begrenzt, in der Regel wird ein Wert von 60 Tagen empfohlen. Der zeitliche Rahmen wird ebenfalls in der HPKP Headerangabe angegeben. Meiner Meinung nach ist eine Angabe über 60 Tage viel zu kurz und erlaubt es, wenn ein Opfer erst nach 60 Tagen die Seite wieder besucht, jedes beliebige valide Zertifikat unterzuschieben. Eine optimale Zeitspanne ist schwer zu definieren aber ich würde, bei langlebigen Zertifikaten und niedriger Besucherfrequenz, aus dem Bauch heraus mindestens 6 Monate empfehlen.

Mit HPKP bietet man Kriminellen allerdings auch eine zusätzliche Angriffsfläche, da diese bei einer möglichen Serverübernahme eigene Zertifikate auf dem Server ablegen können, um deren Hashes in der HPKP abzulegen. Später ziehen sie die eigene Zertifikate zurück und die Besucher lehnen die Verbindung begründet ab. Damit können vor allem Unternehmen erpresst werden. Um das Szenario abzufangen, muss ein Monitoring den HPKP Header durchgehend überprüfen und bei einer Änderung schnell reagieren. Das gilt im übrigen auch für Seiten die HPKP eigentlich nicht einsetzen. Ist plötzlich ein HPKP im Einsatz hat man das gleiche Problem !

In der HPKP Headerangabe kann zusätzlich eine Reporting URL angegeben werden. Der Browser kann und wird in bei einer fehlerhaften HPKP Verbindung ein Meldung an die Adresse versenden. Man kann dazu ein eigene Adresse angeben, dort muss natürlich ein Skript liegen, welches die Meldung entgegen nimmt oder man gibt dort eine der HPKP Reporting Dienste an - einfach mal dazu suchen.


Hash erzeugen

Um einen benötigten Hash zu erzeugen, benötigen wir ein Zertifikat aus der eigenen Trust chain. Wir können also den Hash basierend auf einem Zertifikatsrequest (CSR) oder einem öffentlichem Zertifikat (CRT) generieren lassen.


Erstellung eines Hashs basierend auf einem öffentlichem Zertifikat (CRT) im Base64-Format

openssl x509 -pubkey -in tls.crt | openssl pkey -pubin -outform der | \
openssl dgst -sha256 -binary | base64

Erstellung eines Hashs basierend auf einem Zertifikatsrequests (CSR) im Base64-Format

openssl req -pubkey -in tls.csr | openssl pkey -pubin -outform der | \
openssl dgst -sha256 -binary | base64


Apache Header setzen

Test - Nur Benachrichtigung (60 Sekunden)

Header always set Public-Key-Pins-Report-Only: "\
pin-sha256=\"blkZK/B+V0Z1jRdyB9D5beoGZ1lG8UQC90csvz04k9A=\"; \ 
pin-sha256=\"FNnbbJOO+WDQ3FnyaB+mVeVc6gvAtD/9TIgOwP1PMqE=\"; \ 
max-age=60; \
report-uri=\"http://report.example.com\""

Produktiv - Ohne Benachrichtigung (60 Tage)

Header always set Public-Key-Pins: "\
pin-sha256=\"blkZK/B+V0Z1jRdyB9D5beoGZ1lG8UQC90csvz04k9A=\"; \
pin-sha256=\"FNnbbJOO+WDQ3FnyaB+mVeVc6gvAtD/9TIgOwP1PMqE=\"; \
max-age=5184000;"

Produktiv - Mit Benachrichtigung (60 Tage)

Header always set Public-Key-Pins: "\
pin-sha256=\"blkZK/B+V0Z1jRdyB9D5beoGZ1lG8UQC90csvz04k9A=\"; \
pin-sha256=\"FNnbbJOO+WDQ3FnyaB+mVeVc6gvAtD/9TIgOwP1PMqE=\"; \
max-age=5184000; \
report-uri=\"http://report.example.com\""