HSTS und Let’s Encrypt
Verbindungen zu RandomBrick.de sind schon seit mehreren Jahren mit dem kostenlosen Let’s Encrypt via https verschlüsselt. Eine der Folgefragen, die auftauchten, war über HTTP Strict Transport Security (HSTS) und ob Let’s Encrypt dabei hilft. Da die Frage mehrmals auftauchte, dachte ich, dass es sich lohnen würde, darüber zu schreiben.
Doch was ist HSTS? Obwohl das SSL-Zertifikat an sich schon ein großer Sicherheitsgewinn ist, gibt es immer noch eine potenzielle Lücke, wenn Nutzer HTTP-Inhalte auf HTTPS-Inhalte umleiten.
HSTS und Let’s Encrypt
Nehmen wir an, jemand versucht, randombrick.de aufzurufen. Der Nutzer kann die URL ohne das Protokoll in die URL-Leiste eingeben. Dabei wird die Anfrage standardmäßig auf HTTP gesetzt. Oder der Nutzer hat die Website als Lesezeichen gespeichert. Und zwar zu Zeiten, als die Website noch kein https verwendete.
In diesem Fall stellt der Browser die Anfrage zunächst über einen nicht sicheren Link an den Server. Dann antwortet der Server, indem er den Browser stattdessen auf die HTTPS-Version umleitet. Anschließend wiederholt der Browser die Anfrage, diesmal über eine sichere URL. Schließlich antwortet der Browser mit der sicheren Version der Website.
Während des ersten Austauschs kommuniziert der Benutzer mit der unverschlüsselten Version der Website. Diese kleine Lücke könnte möglicherweise dazu genutzt werden, einen Man-in-the-Middle-Angriff durchzuführen und den Benutzer auf eine böswillige Website statt auf die beabsichtigte HTTPS-Version zu schicken. Diese Lücke kann jedes Mal auftreten, wenn eine Person versucht, über eine nicht sichere URL auf ein Asset zuzugreifen.
HTTP Strict Transport Security (HSTS) hilft bei der Behebung dieses Problems, indem der Browser darauf hingewiesen wird, dass er niemals Inhalte von dieser Website über HTTP anfordern darf. Um HSTS für deine Webseite zu aktivieren, setzt du einen Strict-Transport-Security-Header, wenn auf deine Website über HTTPS zugegriffen wird. Hier ist die Zeile, die ich meiner Virtualhost-Konfiguration für randombrick.de hinzugefügt habe:
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
Wenn diese Zeile zu meiner Serverkonfiguration hinzugefügt wird, enthält jedes Asset, das über HTTPS bereitgestellt wird, den folgenden Header:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Der Header wird nur dann verwendet, wenn er über HTTPS gesendet wird. Wenn er über HTTP gesendet wird, ist er unzuverlässig (ein Angreifer könnte ihn injizieren oder entfernen) und der Browser wird ihn daher ignorieren. Als Folge davon muss diese anfängliche Umleitung immer noch stattfinden. Der Unterschied besteht darin, dass der Server jetzt, nachdem der Browser den Inhalt über eine sichere URL angefordert hat, den HSTS-Header anhängen kann, der dem Browser sagt, dass er nie wieder über HTTP nach etwas fragen soll. Dadurch wird diese Sicherheitsanfälligkeit für jeden zukünftigen Zugriff dieses Benutzers abgeschottet. Als zusätzlicher Bonus erhalten wir durch die Umleitung auch einen kleinen Leistungsschub.
Der Header hat drei Optionen (von denen jede in meinem obigen Beispiel verwendet wurde):
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [;preload]
max-age
Der Parameter max-age ist obligatorisch und gibt an, wie lange der Browser sich merken soll, dass diese Seite nur über HTTPS aufgerufen werden soll.
Je länger, desto besser hier. Nehmen wir an, du stellst ein kurzes Max-Alter von einer Stunde ein. Der Benutzer greift morgens auf deine sichere Seite zu und der Browser schließt nun die Schwachstelle. Wenn er dann nachmittags über eine nicht sichere URL auf deine Seite geht, ist der Strict-Transport-Security-Header veraltet, d.h. die Schwachstelle ist wieder weit offen.
Twitter setzt das maximales Alter auf satte 20 Jahre fest. Ich habe zwei Jahre für meins gewählt, was höchstwahrscheinlich etwas darüber aussagt, dass ich Commitment-Probleme oder so etwas habe.
includeSubDomains
Der Parameter includeSubDomains ist optional. Wenn er eingeschlossen ist, teilt er dem Browser mit, dass die HSTS-Regeln auch für alle Subdomains gelten sollen.
preload
Einige von euch haben vielleicht einen Knick in der HSTS-Rüstung bemerkt. Wenn ein Benutzer aus irgendeinem Grund einen frischen lokalen Status hat (max-age läuft ab, hat die Seite vorher nicht besucht), dann ist diese erste Ladung immer noch anfällig für einen Angriff, bis der Server den HSTS-Header zurückgereicht hat.
Um dem entgegenzuwirken, hat jeder moderne Browser eine vorinstallierte HSTS-Liste von Domains, die im Browser fest als nur HTTPS codiert sind. Dadurch weiß der Browser, dass er nur HTTPS-Assets von deiner URL anfordern kann, ohne darauf warten zu müssen, dass dein Webserver dies mitteilt. Damit wird der letzte kleine Knick in der Panzerung versiegelt, aber er birgt ein erhebliches Risiko.
Wenn der Browser deine Domain in seiner HSTS-Liste hartkodiert hätte und du diese entfernen müsstest, kann es Monate dauern, bis die Löschung in einem Browser-Update an die Benutzer weitergegeben wird. Es ist kein einfacher Prozess.
Aus diesem Grund ist es einfacher, deine domain in einer preload Liste zu speichern, diese du jedoch manuell übermitteln musst. Dein HSTS-HEader muss sowohl sowohl den includeSubdomains Parameter als auch den letzten preload Parameter enthalten.
Aktiviert der Let’s Encrypt-Client HSTS?
Der Let’s Encrypt-Client kann HSTS aktivieren, wenn du das (derzeit undokumentierte) hsts-Flag verwendest.
./letsencrypt-auto --hsts
Der Grund, warum es nicht standardmäßig aktiviert ist, ist, dass HSTS im Falle eines Fehlers große Kopfschmerzen verursachen kann.
Nehmen wir an, du hast HSTS aktiviert. Irgendwann geht etwas mit deiner SSL-Konfiguration schief und dein Server ist nicht in der Lage, eine sichere Anfrage zu bedienen. Dein Server kann die sichere Anfrage nicht erfüllen, aber der Browser (wegen des HSTS-Headers) kann nichts anfordern, was unsicher ist.
Du befindest dich in einer Sackgasse und deine Besucher können den fraglichen Inhalt oder das betreffende Asset nicht sehen. Dies bleibt so lange der Fall, bis entweder deine SSL-Konfiguration wiederhergestellt ist oder der HSTS-Header abläuft. Das kann sich sehr schnell sehr negativ auf das Einkommen deiner Webseite auswirken.
Wegen dieses Risikos muss HSTS eine Option sein, die ein Benutzer in Let’s Encrypt angeben muss – trotz seiner Bedeutung.
Fazit zu HSTS und Let’s Encrypt
Das heißt nicht, dass der Prozess nicht verbessert werden könnte. Die GUI-Version des Clients stellt dir derzeit eine Vielzahl von Fragen, während du dein Zertifikat einrichtest. Eine dieser Fragen lautet, ob du den gesamten HTTP-Verkehr auf HTTPS umleiten möchtest.
Wenn der Entwickler sich entscheidet, den gesamten HTTP-Verkehr auf HTTPS umzuleiten, wäre es doch schon, wenn die nächste Frage lautet: „Möchten Sie, dass Let’s Encrypt HSTS einrichtet?“, wahrscheinlich mit einer Warnung, die den Entwickler dazu auffordert, sicherzustellen, dass alle Inhalte auf HTTPS laufen.
Standardeinstellungen sind wichtig und die meisten Nutzer werden sich daran halten. HSTS ist wichtig und HTTPS ist … nun … unvollständig ohne HSTS. Wenn wir es mit HTTPS Everywhere ernst meinen, dann müssen wir HSTS genauso ernsthaft aktivieren, wie wir sicherstellen, dass jeder Inhalte über HTTPS anbietet.
Einen Weg zu finden, um die Nutzung zu fördern, wann immer es möglich ist, würde einen großen Beitrag zur Erhöhung der Sicherheit im Web leisten und eines der Hauptprinzipien der Let’s Encrypt-Initiative befolgen:
Let’s Encrypt will serve as a platform for advancing TLS security best practices, both on the CA side and by helping site operators properly secure their servers.
Geek, Blogger, Consultant & Reisender. Auf seiner Detail-Seite findest du weitere Informationen über Benjamin. In seiner Freizeit schreibt Benjamin bevorzugt über Technik-Themen. Neben Anleitungen und How-To’s interessieren Benjamin auch Nachrichten zur IT-Sicherheit. Sollte die Technik nicht im Vordergrund stehen, geht Benjamin gerne wandern.