Die Aufgabenstellung für einen Browser ist im ersten Moment eigentlich sehr simpel: ein Browser soll Internetseiten anzeigen! Doch diese Aufgabe entpuppt sich bei genauerer Betrachtung als Mammutprojekt: tausende Web-Standards müssen unterstützt werden, damit der Browser all die verschiedenen HTML-Tags, CSS-Attribute und JavaScript-API’s kennt, die sich in den letzten 25 Jahren angesammelt haben. Zahlreiche Komfortfunktionen sollen das Browsing-Erlebnis so unkompliziert wie möglich machen, Entwickler-Werkzeuge das Debugging von Seiten erleichtern und nicht zuletzt braucht es ein Erweiterungs-System – denn ohne Plugins und Toolbars lassen sich wichtige Funktionen nicht nachrüsten. Neben all diesen “offensichtlichen” Funktionen, verfügen moderne Web-Browser aber auch noch über zahlreiche Funktionen, die den Nutzer vor Angriffen schützen sollen. Viele dieser Funktionen sind “einfach da”, andere aber müssen explizit aktiviert werden – und das geht durch HTTP Security-Header.
Beim Wort “Header” wird der Webentwickler-Laie wohl spontan an den <head>-Bereich eines HTML-Dokuments denken – HTTP-Header aber sucht man hier vergebens, denn im HTML-Head befinden sich nur, Sie ahnen es schon, HTML-Header.
Wo also verstecken sich die HTTP-Header? Das HTTP-Protokoll bildet bis heute die Basis für das World-Wide-Web, also diese wundersame Welt, die wir mit unserem Web-Browser betrachten können. HTTP ist gewissermaßen die “Sprache”, mit der Browser Daten jeder Art bei einem Server anfragen können – und der Server beantwortet diese Anfrage mit einer Antwort, die sowohl allgemeine Informationen zur Antwort enthält, als auch die eigentlichen Nutzdaten, also die Datei die vom Server angefordert wurde. Die “allgemeinen Informationen” werden hierbei vorab im Kopf-Bereich der Antwort übertragen und bilden somit, Sie ahnen es schon, den Head der Response. In diesem Head werden dann gleich mehrere Informationen übertragen, jeder Informations-Datensatz ist dabei ein Header.
Diese recht trockene Beschreibung wird “lebendiger”, wenn man im “Netzwerk”-Tab der Browser-Entwicklertools mal nach den “Kopfzeilen” (Firefox) bzw. “Headers” (Chrome) sucht:
Mithilfe dieser Entwickler-Werkzeuge bekommt man einen Einblick in die Informationen, die hier “hinter den Kulissen” übertragen werden. Der Header “Content-Length” teilt dem Browser z.B. mit, wie groß die übermittelte Datei ist, Cache-Header geben an, ob und wie lange eine Datei im Browser-Cache abgelegt werden darf und der Content-Type teilt dem Webbrowser mit, welche Art von Daten hier überhaupt übertragen werden.
Die versteckten Sicherheitsfunktionen durch HTTP Security-Header aktivieren
Was haben diese Header aber nun mit Sicherheitsfunktionen zutun? Moderne Webbrowser verfügen über eine Vielzahl von Funktionen, die Nutzer vor bösartigen Angriffen schützen sollen. Einige dieser Sicherheitsfunktionen wurden bereits bei der Erstellung der zugehörigen Webstandards berücksichtigt (als Beispiel sei hier die Same-Origin-Policy genannt), andere Schutzfunktionen aber wurden erst definiert, als aus einer bisher legitim verwendeten Webfunktion ein ernstzunehmender Angriffsvektor wurde. So sind z.B. iFrames eine grundsätzliche praktische Sache, erlauben Sie doch die Einbettung von Webseiten ineinander. Leider wurde aber dann das sog. Clickjacking erfunden, bei dem man Nutzer glauben lässt, dass Sie mit einer anderen Website agieren, die über ein Iframe in der angreifenden Seite eingebettet ist – Mausklicks oder Tastatureingaben (z.B. die Online-Banking-Daten) werden aber in Wahrheit in Eingabefelder auf der angreifenden Seite eingegeben, die transparent über der eingebetteten Seite liegen. Hier sind die Browser-Hersteller nun in der Bredouille: wie sollen sie Nutzer vor Clickjacking schützen, wenn sie nicht wissen können ob ein iFrame legitim oder bösartig ist?
Eine nachträglich eingeführte Sicherheitstechnik verursacht also Probleme bei bestehenden Webseiten, weshalb Browserhersteller solche Schutzfunktionen in der Regel dann nicht standardmäßig aktivieren, sondern diese Entscheidung dem Nutzer oder der Website überlassen – und genau hier kommen die HTTP Security-Header ins Spiel! Sie erlauben einem Seitenbetreiber, die zusätzlichen Sicherheitsfeatures zu aktivieren, wenn die jeweilige Seite damit kompatibel ist! Somit werden die “Wachhunde” des Browsers aktiv, die normalerweise im Hintergrund schlummern, was in bestimmten Angriffsszenarien erhebliche Sicherheitsgewinne mit sich bringen kann.
Security-Header: Chancen und Grenzen
“Angriffsszenarien” ist hier ein gutes Stichwort, denn prinzipbedingt können die Security-Header nur dann helfen, wenn ein Angreifer keinen Zugriff auf den Code der Seite und/oder die Serverkonfiguration hat – denn genau dort werden die Security-Header definiert und können somit auch leicht wieder entfernt werden, wenn der Zugriff der Angreifers weit genug reicht. HTTP Security-Header können somit in Worst-Case Szenarien nur begrenzt helfen, nichtsdestotrotz erweisen sie sich auch hier oftmals als nützlich, weil automatisiert ausgeführte Angriffe (das ist der Regelfall) die Existenz der Header nicht prüfen geschweige denn sie entfernen – sie können dann selbst bei gehackten Seiten noch Nutzer schützen.
Wesentlich effektiver sind die Header aber bei Angriffsszenarien, bei denen der Angreifer keine oder nur “geringe” Rechte (z.B. als normaler Redakteur im CMS) hat. Hier können die serverseitig gesetzten Header nicht verändert oder gar entfernt werden, womit sich die Schutzwirkung voll entfalten kann.
Übersicht über die Header
Im Folgenden möchte ich einen kleinen Überblick über die sicherheitsrelevanten Header geben, damit die jeweilige Funktionsweise und das Angriffsszenario klar wird.
X-Frame-Options
Diesen Header haben wir thematisch bereits angeschnitten: X-Frame-Options steuert, ob eine Website in einem frame eingebettet werden darf. Der Header schränkt somit nicht die Nutzung von iframes auf der eigentlichen Seite ein – aber er sorgt zuverlässig dafür, dass Browser die entsprechende Seite nicht laden, wenn sie in einer anderen, möglicherweise bösartigen Seite eingebettet wurden. Neben dem kompletten Verbot der Einbettung (DENY) unterstützt der HTTP Security-Header noch zwei andere Werte:
SAMEORIGIN erlaubt die Einbettung der Seite in sich selbst
ALLOW-FROM erlaubt die Freigabe der Einbettung auf frei definierbaren Seiten
X-XSS-Protection
Aktiviert eine generische Funktion zur Unterdrückung von sog. Reflective Cross-Site-Scripting Attacken. Bei diesem Angriffstyp wird JavaScript- oder HTML-Code, der über die URL oder POST-Parameter an die Seite übergeben werden wieder an den Nutzer ausgegeben, also “reflektiert”. Bei einer solchen Lücke lassen sich dann z.B. Links konstruieren, die bösartiges JavaScript im Browser des Nutzers ausführen.
Die XSS-Protection der Browser unterdrückt genau das.
X-Content-Type-Options
Woher weiß der Browser eigentlich, dass er beim Aufruf von example.org/text.html ein HTML-Dokument ausgeliefert bekommt, dass dann auch als solches zu rendern ist? Oder das viel spannendere Szenario: wie erkennt der Browser, dass sich hinter einer bestimmten URL ein Bild verbirgt? Klar, die verwendete Dateiendung hilft, aber auch diese ist nicht immer vorhanden, was macht die Software dann?
In der Regel wird der Browser dann auf den Content-Type Header zurückgreifen, den der Server mitliefert. Der Wert “image/jpeg” führt z.B. dazu, dass der Browser die zurückgelieferten Daten als Bild interpretiert.
Was aber, wenn auch dieser Header fehlt? Dann wird es spannend, denn der Browser wird dann versuchen, den korrekten Inhaltstyp für die Daten zu erraten. Dies ist problematisch, wenn ein Angreifer z.B. HTML-Code in eine Datei mit dem Namen “bild.jpg” eingebettet hat und es schafft, diese Datei auf eine angreifende Website hochzuladen, die keinen Content-Type übergibt. Der Browser muss nun erraten, welcher Inhaltstyp zur Datei passt – und wenn er den Inhalt der Datei einliest, wird das wahrscheinlich Resultat “text/html” sein. Der bösartige Code wird dann ausgeführt.
Hier kommt unser HTTP Security-Header ins Spiel! Durch den Wert “nosniff” kann man die “Ratefunktion” der Browser unterdrücken und den Angriffsvektor dadurch schließen.
Strict-Transport-Security
Bei sogenannten Man-In-The-Middle Attacken (kurz MITM) leitet ein Angreifer den Datenverkehr zwischen Opfer und Server über sich um, er sitzt bei der Kommunikation somit nun “in der Mitte”, kann Informationen auslesen und Antworten manipulieren. Zuverlässigen Schutz bietet hier die Verschlüsselung über HTTPS – aber was ist, wenn der Angreifer dem Nutzer einen http-Link schickt und der Aufruf somit unverschlüsselt erfolgt? Hier hilft der HTTP Strict-Transport-Security (kurz HSTS) Header: er teilt dem Browser mit, dass die gerade aufgerufene Seite für einen frei definierbaren Zeitraum (sinnvolle Werte liegen bei mindestens 6 Monaten) ausschließlich per HTTPS aufgerufen werden darf. HTTP-Verbindungen werden dann automatisch in HTTPS-Aufrufe umgewandelt.
Referrer-Policy
Über diesen Header lässt sich steuern, ob und in welchen Fällen der sog. Referrer-Wert bei ausgehenden Links übergeben werden soll. Klickt z.B. ein Nutzer, der auf example.org surft, auf einen Link der zu domain.tld zeigt, so wird der Browser eine Info an domain.tld übergeben, dass dieser Aufruf von example.org kommt.
Der Referrer lässt sich nicht direkt für Angriffe nutzen, ist allerdings durchaus relevant für den Datenschutz. Über den Wert “no-referrer” lässt sich die Übertragung grundsätzlich unterdrücken, womit die Herkunft der Nutzer beim Verlassen der eigenen Seiten verschleiert wird.
Feature-Policy
Die Feature-Policy ist ein relativ neuer Header und erlaubt es, die Nutzung bestimmter Funktionen, die für die Sicherheit oder den Datenschutz des Nutzers relevant sind, auf der Seite grundsätzliche zu verbieten. Zu diesen Funktionen gehören z.B. die Aktivierung von Webcam oder Mikrofon, der Abruf des Standorts, die Nutzung der Vibrationsfunktion oder die Aktivierung der ebenfalls noch relativ neuen Payment-API, die z.B. bei ApplePay Verwendung findet.
Über diesen Header kann man somit Schadcode unterdrücken, der es insbesondere auf Nutzer-Daten abgesehen hat.
Content-Security-Policy
Der wohl mächtigste HTTP Security-Header, der aber auch das größte Potenzial für Probleme mit sich bringt, ist die Content-Security-Policy, kurz CSP. Über die CSP lässt sich detailliert steuern, ob die Verwendung von verschiedensten “Datentypen” auf einer Seite erlaubt ist – und falls ja, aus welcher “Quelle” die Daten stammen müssen, damit sie als vertrauenswürdig gelten und somit ausgeführt werden.
Ein Beispiel:
default-src ’self‘; script-src ’self‘ https://webstats.domain.tld; frame-src ’self‘ https://www.youtube.com/ https://www.youtube-nocookie.com/ https://www.google.com/; img-src ’self‘ data: https://img.youtube.com https://i1.ytimg.com https://i.ytimg.com https://i9.ytimg.com https://s.ytimg.com
Die “Grundregel” für alle Datentypen wird in der default-src festgelegt. Der Wert “self” bedeutet hierbei, dass nur Daten zugelassen sind, die von selben Domain geladen werden, von der auch die Website abgerufen wird. Wird dieser Header auf www.example.org gesetzt, dürften JavaScript, Bilder, CSS und Co dann also nurnoch von www.example.org geladen werden – und eingeschmuggelter Code, der von evilsite.tld geladen wird, wird vom Browser blockiert.
Im vorliegenden Beispiel wird weiterhin noch das Laden von Javascript (script-src) von webstats.domain.tld, sowie die Einbettung von Youtube-iFrames und das entsprechende Laden von Bildern von den Youtube-Bildservern (i.ytimg.com) erlaubt.
Besonders spannend wird die CSP dann, wenn, wie im vorliegenden Fall, das Laden von Daten verhindert wird, die direkt in der Seite eingebettet sind – also z.B. JavaScript-Code in einem <script>-Tag oder onclick-Attribut. Cross-Site-Scripting Attacken basieren oftmals darauf, dass es einem Angreifer gelingt, Script-Code direkt in die Seite einzuschleusen – und dieser Fall wird durch die CSP komplett geblockt.
Leider fallen dieser Blockade aber legitime Inline-Skripte zum Opfer, und da diese Inline-Skripts in gängigen CMS und Webapplikationen quasi omnipräsent sind, führt diese Konfiguration oft zu massiven Problemen. Der bestmögliche Workaround ist hierbei das explizite Whitelisten von vertrauenswürdigen Inline-Skripts über nonces bzw. Hashs, was z.B. im Mozilla Blog beschrieben ist. Die Alternative ist die grundsätzliche Freigabe von inline-Daten über das unsafe-inline Attribut der CSP – diese Maßnahme ist zwar simpel, hebelt allerdings leider auch große Teile der CSP-Schutzfunktion aus.
Bestandsaufnahme: was ist bereits auf der eigenen Seite im Einsatz?
Um den aktuellen Absicherungsstand der eigenen Seite zu prüfen, reicht es im Grunde genommen einen Blick in die Entwickler-Tools des Browsers zu werfen. Angenehmer sind jedoch Tools wie SIWECOS oder SecurityHeaders.com, die die verwendeten Header auslesen, die Konfiguration prüfen und das Ergebnis grafisch darstellen.
Überzeugt? HTTP Security-Header aktivieren!
Die Aktivierung der Security-Header erfolgt vorzugsweise über die Konfiguration des Webservers, z.B. durch eine .htaccess Datei oder die Nginx Konfiguration. Ein minimalistisches Beispiel für die .htaccess sieht z.B. so aus:
# Extra Security Headers <IfModule mod_headers.c> Header set X-XSS-Protection "1; mode=block" Header always append X-Frame-Options SAMEORIGIN Header set X-Content-Type-Options nosniff Header set Strict-Transport-Security max-age=17280000 Header set Referrer-Policy no-referrer Header set Feature-Policy "camera 'none'; microphone 'none'; geolocation 'none'; payment 'none';" Header set Content-Security-Policy "default-src 'self';" </IfModule>
ACHTUNG: dieses Beispiel MUSS an die eigene Website angepasst werden! Insbesondere Feature- und Content-Security-Policy werden in der vorliegenden Form bei der überwiegenden Zahl der Websites zu Probleme führen!
Fazit
Die HTTP Security-Header sind ein wichtiges Werkzeug, um die zusätzlichen Sicherheitsfunktionen moderner Browser zu aktivieren. Sie erfordern zwar ein wenig Einarbeitungszeit, aber der Sicherheitsgewinn wiegt diesen zeitlichen Einsatz auf.
Titelmotiv: Pixabay Free Pictures
- HTTP Security-Header – Wie Sie die schlummernden Wachhunde des Browsers wecken - 6. November 2018
- Wieso ist das so langsam? – Joomla-Debugging von Performance-Problemen - 15. Oktober 2018