Header für HTTP Public Key Pinning – HPKP

Vor knapp einem Jahr hatte ich das Thema „Headereinträge zur Verbesserung der Sicherheit“ von Webseiten mit und ohne SSL schon einmal als Thema. Da es auch dieses Jahr u.a.

  • mit Heartbleed und Poodle weitere Angriffszenarien bzw. Lücken gab
  • bestätigt wurde, dass an Internetknotenpunkten von Geheimdiensten die Verbindungen abgehört werden
  • und gerade vor kurzem beim Thema SSL nach der Ankündigung des BND, künftig Exploits (also bekannte Wege und Anweisungen, um Lücken auszunutzen) aktiv verwenden und ankaufen wollen
  • sowie es generell immer irgendjemand „Bösen“ gibt, der aus Langeweile oder warum auch immer Schaden verursachen will,

war es mal wieder an Zeit das Thema, auch wenn es nur ein kleiner Tropfen auf dem heißen Stein ist, erneut aufzunehmen.

Es handelt sich auch diesmal wieder um einen Headereintrag, der per .htaccess gesetzt und so an die Browser übermittelt wird. Der nachfolgend beschriebene Eintrag gilt für den Apache Webserver mit dem Modul „mod_headers“. Allerdings macht er nur Sinn, wenn Ihr ein SSL-Zertifikat einsetzt.

HTTP Public Key Pinning (HPKP)

Der Server sendet hierbei an den Browser einen Pin, der aus den Hashes der kryptographischen öffentlichen SHA-Schlüssels eures Zertifikats erstellt wird und einem zusätzlichen Zeitwert besteht. Unterstützt der Browser dieses sog. Pinning, dann speichert er diese Information und akzeptiert künftig nur noch die Verbindungen, bei denen das SSL-Zertifikat einen der mitgesendeten gepinnten Schlüssel enthält. Es gibt für die Erstellung des Pins auch ein Skript: https://github.com/hannob/hpkp

Ein Beispiel für einen derartigen Pin ist folgender .htaccess-Eintrag:

# HTTP Public Key Pinning (HPKP) aktivieren
# Pflichtangabe: „max-age“ und „pin-Schluessel“
# Optional: „includeSubDomains“ sowie „report-uri“
Header set Public-Key-Pins „pin-sha256=“E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=“; pin-sha256=“LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=“; max-age=2592000; includeSubdomains; report-uri=“https://example.com/hpkp.php“

Bedeutung: Erlaube für maximal 60 Tage (=max-age) nur SSL-Verbindungen zu meiner Domain und allen Subdomains (=includeSubdomains) mit den beiden öffentlichen Schlüsseln (=pin-sha256). Für den Fall, dass es zu einer Verbindung mittels https kommt, aber kein mit einem Pin übereinstimmendes Zertifikat ausgeliefert wird, sende mir an die angegebene Adresse einen JSON-codierten Fehlerbericht (=report-uri).

Einen kleinen Haken hat die ganze Sache leider: Verliert ihr den privaten Schlüssel, werden unabsichtlich alle Besucher ausgesperrt; zumindest für den definierten Zeitrahmen der max-age. Deshalb muss man auch zwei Schlüssel definieren, der zweite ist der Ersatzschlüssel. Dieser wird auch dann genutzt, sobald ein neues Zertifikat eingesetzt wird. Man nutzt dann den bereits hinterlegten Ersatzschlüssel für die Ausstellung des neue Zertifikats. Sobald das neue im Einsatz ist, ersetzt man den Ersatzschlüssel dann wiederum durch einen Neuen.

Browserunterstützung:

HPKP wird noch nicht flächendeckend unterstützt, da es sich derzeit noch um einen Entwurf handelt. Nach meiner Einschätzung könnte es aber in der ersten Jahreshälfte 2015 als offizieller Standard der Internet Engineering Task Force (IETF) anerkannt werden:
http://tools.ietf.org/html/draft-ietf-websec-key-pinning-11

Genutzt wird der neue Key-Pinning-Header derzeit nur in Google Chrome sowie Chromium. Firefox hat angekündigt, die Technologie ab der Version 35 unterstützen zu wollen.

3 Antworten

  1. Steffen Gebert 12. November 2014 / 21:36

    Danke Dietmar, wieder mal was gelernt!
    Vom Zertifikats-Pinning über Header hatte ich bisher gar nichts gehört – nur dass die ganz großen Seiten mit ihren Fingerprints fest in den Browsern drin sind.

Schreibe einen Kommentar

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