Hallo zusammen, Textwand folgt.
Ich lese im Internet immer wieder Mythen über sicherheitsrelevante HTTP Response Header (aka HTTP Security Header). Beispielsweise schreiben manche Blogger, man brauche eine lange Liste an Security Headern, damit die Webseite „sicher“ sei. Andere empfehlen Header, die entweder kaum ein Webbrowser spricht (da zu neu) oder welche die seit Jahren gar nicht mehr unterstützt werden (da permanent entfernt).
Ich teile nachfolgend ein paar Informationen, die ich herausgefunden habe. Vielleicht ist das für ein paar Admins/Neulinge interessant zu wissen (Achtung: Ist weder abschließend vollständig noch alles ganz neues Wissen):
- Security Header sollten eine weitere Schutzschicht und nicht die einzige Schicht bei eurer Webapplikation sein (Stichwort: Defense in depth). Wenn eure Webapplikation anfällig für Cross-Site-Scripting (XSS) ist, können euch HTTP Security Header nicht retten. Deshalb gilt: Die darunterliegende Webapplikation oder der Webserver müssen bereits kontinuierlich aktuell gehalten und ausreichend abgesichert werden. Einen Security Header on top auf eine unsichere Webapplikation zu klatschen, ist wie ein Pflaster auf ein gebrochenes Bein.
- Security Header müssen clientseitig unterstützt und befolgt werden. Das heißt ganz konkret: Die gängigsten Webbrowser unterstützen die meisten Security Header und können damit umgehen. Viele nicht so bekannte Webbrowser, Apps oder irgendwelche anderen Webclients (wie bspw. über Python, Java) können nur einen Ausschnitt der möglichen Security Header. Das bedeutet, bei diesen Clients sind die gesetzten Security Header wirkungslos, da sie für den Client praktisch nicht da sind. Dazu kommt, dass gerade die experimentellen Security Header immer wieder modifiziert werden und deshalb auch die gängigsten Webbrowser nicht unbedingt alles unterstützen (Beispiel folgt). Siehe vor allem die Webseite caniuse.com bzw. developer.mozilla.org/de/docs/Web/HTTP/Headers für unterstützte Header. Und natürlich ist die Clientseite aus Security-Sicht nicht mehr unter Kontrolle des Serverbetreibers. Angreifer könnten Clients so modifizieren, dass diese die Security Header einfach ignorieren und damit komplett wirkungslos machen.
- Nur weil irgendein Webtool (z.B. securityheaders.com) sagt, bestimmte Header fehlten, heißt das noch lange nicht, dass man diese Header auch braucht. Teils schlagen diese Tools Header vor, die kaum ein Webbrowser versteht oder sie bringen kaum „echte“ Sicherheit. (Auch hier gleich Beispiele)
- Und noch etwas zu report-to, report-uri, Reporting API, Reporting-Endpoints: Einige der gleich genannten Security Header erlauben das Setzen eines Reporting Endpoints. Das bedeutet, wenn der Client (Webbrowser) nach Empfangen des Headers diesen verarbeitet und irgendein Verstoß auftritt, kann der Webbrowser einen Report an den Endpoint schicken. Der Betreiber des Endpoints (eben bspw. derselbe Betreiber wie der der Webseite) kann dann diesen Report ansehen und entsprechend agieren. Ich habe mir Reports über mehrere Monate schicken lassen. Aus meiner Sicht ist das Thema nur sinnvoll, wenn man selbst Entwickler der Webapplikation ist und diese Reports für Debugging bzw. Anpassen der Header braucht. Für eine Standardwebseite™ sollte man keine Gründe haben, dieses Feature zu nutzen. Insbesondere, weil man bei sicherheitsrelevanten Verstößen auf Clientseite im Regelfall als Serverbetreiber sowieso gar nichts machen kann. Und natürlich kann man bspw. mit uBlock Origin solche Reports im Client abschalten oder die Endpoint-Domain irgendwo blockieren.
Security Header, die man aktuell (Mai 2021) setzen sollte:
- HTTP Strict Transport Security (HSTS): Dieser Header signalisiert dem Client, dass er die Webseite zukünftig über HTTPS statt HTTP aufrufen soll. Dies gilt aktuell als Best Practice. Die gängigsten Webbrowser sollen sogar in naher Zukunft erst über HTTPS und dann via HTTP verbinden (HTTPS by default), wodurch dieser Header an Bedeutung verlieren könnte.
- Referrer-Policy: Dieser Header signalisiert dem Client, was er mit dem „Referrer“-Feld machen soll. Der Client inkludiert den Referrer in seinen HTTP Requests an den Server. Angreifer könnten theoretisch vertrauliche Informationen über den Referrer auslesen. Deshalb kann man den Referrer hier abschalten. Auch das muss natürlich der Client verstehen und auch tun. Natürlich muss man aufpassen, falls die Webapplikation den Referrer braucht.
- X-Content-Type-Options: Dieser Header signalisiert dem Client, dass er die vom Server gesetzten MIME Typen bei CSS und JavaScript beachten soll. Hier gab es früher das Problem, dass Clients den MIME Typen eventuell geraten haben und hier Angriffe möglich waren. Bei diesem Header gibt es nur eine einzige Konfigurationsmöglichkeit. Da kann man eigentlich nicht viel falsch machen.
- Content Security Policy: Dieser Header ist recht mächtig und signalisiert dem Client verschiedene Dinge. Beispielsweise woher der Client JavaScript und CSS laden und ausführen darf, aber auch, ob eine Webseite als iframe geladen werden darf. Hier wird man in der Praxis viele Schwierigkeiten haben, weil man oft nicht weiß, was man denn alles verbieten darf, ohne dass die Webapplikation nicht mehr korrekt funktioniert. Aus meiner Sicht ist eine superstrikte CSP in der Praxis kaum möglich. Das sollte andererseits auch kein Problem sein, wenn die Webapplikation aktuell gehalten und abgesichert wird.
Security Header, die man aktuell (Mai 2021) nicht mehr setzen braucht:
- HTTP Public Key Pinning (deprecated): Dieser Header wird von keinem gängigen Webbrowser mehr unterstützt und dementsprechend ignoriert.
- X-Xss-Protection (deprecated): Dieser Header wird von keinem gängigen Webbrowser mehr unterstützt und dementsprechend ignoriert.
- Expect-CT (deprecated): Dieser Header soll schon nächsten Monat (Juni 2021) offiziell beerdigt werden und fliegt dann aus den Webbrowsern raus.
- Expect-Staple (unklar): Dieser Header ist laut meiner Recherche nie wirklich in gängigen Webbrowsern angekommen, sondern ein Entwurf von Scott Helme, weshalb der Header in seinem Tools securityheaders.com auch empfohlen wird. Ich würde den Header nicht setzen, gerade weil er eben nichts bringt. Er ist einfach nur da.
- X-Frame-Options (Legacy): Dieser Header wird heutzutage über die frame-ancestors Direktive der Content Security Policy gesetzt. Man sollte X-Frame-Options nur setzen, wenn man auch veraltete Clients unterstützen muss, die Probleme mit der Content Security Policy haben (Beispiel: Internet Explorer 11).
Security Header, die man aktuell (Mai 2021) nicht setzen aber im Auge behalten sollte:
- Permissions-Policy (Entwurfsstatus): Dieser Header hieß vormals Feature-Policy. Ähnlich der Content Security Policy kann man hier recht viele Features des Webbrowsers ausschalten, wenn man sie nicht braucht. Das Problem ist aber, dass dieser Header durch den neuen Namen und die vielen unterschiedlichen Features in jedem Webbrowser einen Wildwuchs an Optionen hat und weitestgehend ignoriert wird. Ihn zu setzen, ergibt aktuell keinen Sinn.
- Cross-Origin-Embedder-Policy, Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy (Living Standard): Diese Familie an Headern adressiert Cross-Origin-Isolation, was nach Spectre und Meltdown relevant ist. Diese sollte man sich definitiv anschauen, aber auch beachten, dass nur die modernsten Webbrowser-Versionen damit umgehen können. Außerdem basteln Mozilla und Google gerade mehr und mehr Isolation by default in ihre Webbrowser.
- Clear Site Data (Entwurfsstatus): Dieser Header ermöglicht lokale Daten der jeweiligen Webseite löschen zu lassen (z.B. Cookies, LocalStorage, Cache). Neuere Webbrowser sollten damit bereits umgehen können. Kann man sich auch anschauen, falls relevant.
So viel zu meiner Recherche. Ich hoffe, es hilft euch.
TL;DR: Diverse Blogs und Tools empfehlen alle paar Wochen, dass man sämtliche HTTP Security Header von A bis Z setzen solle, weil eine Webseite sonst unsicher sei. In der Praxis werden viele dieser ständig empfohlenen Header aber entweder gar nicht mehr oder noch nicht unterstützt, weshalb sie nur subjektiv gefühlt mehr Sicherheit bringen, aber nicht objektiv praktisch.