Inglorious Headers

Inglorious Headers

Veit Hailperin
von Veit Hailperin
am 21. Januar 2016
Lesezeit: 18 Minuten

Schutz braucht nicht viel zu kosten. Weder Zeit noch Geld. Für Privatpersonen dokumentiere ich das in der Reihe Gesunde Paranoia. Aber auch für Serverbetreiber gibt es Tricks, mit denen man mit wenig Aufwand seine Sicherheit massgeblich verbessern kann. In diesem Artikel geht es in erster Linie um die Header, die in der http-Antwort mitgeschickt werden, um das Browserverhalten beeinzuflussen um u.a. Cross-Site-Scripting (XSS) Angriffe zu verhindern.

Bei XSS-Angriffen wird Javascript-Code in Webseiten eingeschleust. Es gibt verschiedene Klassen von XSS. Sogenannte Reflected XSS, bei denen eine Benutzereingabe ungefiltert zurückgegeben wird in einer darauf folgenden Antwort. Es ist die am häufigsten gefundenen XSS Schwachstelle. Stored oder Persistent XSS, bei denen zusätzlich die Eingabe auf der Webseite gespeichert wird, zum Beispiel bei Gästeforen. DOM-based XSS, bei denen Browser-seitiger, aktiver Code (z.B. Javascript) Benutzereingaben unsicher verwendet und Mutation-Based XSS, bei denen der Browser die Eingabe leicht verändert und dadurch nicht funktionierenden Code in Code verändert. Andere, obskure XSS werden nicht berücksichtigt.

Content-Type

Während der Browser-Kriege, bei denen Browser um die Vormacht im Web stritten, wurden viele Browserfunktionen eingeführt um möglichst alle Webseiten korrekt anzuzeigen. Abgesehen davon, dass dies schlechtes Design förderte, sind auch die Folgen in Bezug auf die Sicherheit bis heute spürbar. Eines davon ist das Erraten des Zeichensatzes eines Dokumentes. Das Problem ist mehrschichtig. XSS-Filter sind häufig nur in einem Zeichensatz (charset) definiert. Das heisst, dass diese Filter leicht umgangen werden können, wenn der bösartige Javascript-Code in einer anderen Kodierung daherkommt. Ein klassisches Beispiel hierfür ist UTF-7.

UTF-7 ist eine Kodierung, welche ursprünglich für SMTP Gateways entwickelt wurde, da manche Gateways nicht mit 8-bit-Zeichen umgehen konnten. UTF-7 ist allerdings auch eine Kodierung, welche sehr leicht zu erkennen ist. Damit konnte ein Filter, welcher ein reguläres XSS wie

<script>alert(1)</script>

erkennt, aber der Browser die Funktion zum Zeichensatzerraten aktiviert hat umgangen werden mit

+ADw-script+AD4-alert(1)+ADw-/script+AD4-

da der Browser +ADw- als kodierte UTF-7 kodiertes < erkannte, und das Charset zur Darstellung anpasst. Mehr Details bezüglich UTF-7 Angriffen bietet OWASP in ihrem XXS-Filter-Evasion Cheat-Sheet. Die Anzahl existierender Kodierungen ist riesig. Hackvertor bietet eine Auswahl verschiedener Charsets und hilft während Web Application Penetration Tests.

Der Content-Type Header kann folgendermassen gesetzt werden:

Content-Type: text/html; charset=UTF-8

Damit wird der Browser angewiesen, den Zeichensatz nicht zu erraten und verbessert dadurch den Schutz vor diesen Angriffen.

X-Content-Type-Options

Ein weiteres Kind der Browser-Kriege ist die Funktion zum Erraten des Inhalts. Wenn ein Browser auf Basis von Content-Type-Guessing annimmt, dass eine Datei heruntergeladen werden soll, kann dies zum Beispiel durch Drive-By-Download-Angriffe ausgenutzt werden. Auch Chrome ist dem gegenüber nicht gefeit. Grössere Auswirkung haben sogenannte Cross-Site Script Inclusion-Angriffe (XSSI), bei denen z.b. CSV und JSON abfliessen können, indem sie in einer bösartigen Seite per script-Tag eingebunden werden. Dadurch, dass sie als Script eingebunden werden, unterliegen sie nicht mehr der Same-Origin Policy und obwohl sie nicht dann nicht als Script ausgeführt werden können – da sie keine Script sind – können die Daten mittels Error Message geleakt werden. Diverse CVEs sind diesbezüglich veröffentlicht worden.

Dies stark einzugrenzen ist simpel und steht bereits im Titel. Der empfohlene Wert ist:

X-Content-Type-Options: nosniff

Die Klasse der XSSI-Verwundbarkeiten ist damit nicht komplett verhindert, wie aktuelle Forschung zeigt, aber der Header deckt den Grossteil der XSSI ab.

X-XSS-Protection

Dem Namen nach würde man annehmen, dass dieser Header gegen XSS schützt. Bei korrekter Verwendung korrigiert er allerdings maximal zurück auf den Schutz, den Browser Internet Explorer (IE) sowie Google Chrome ohnehin bieten. Beide Browser geben dem Benutzer die Möglichkeit, ihren XSS-Schutz zu deaktivieren. Der Header korrigiert diese Einstellung für die Webseite zurück. Der empfohlene Wert ist:

X-XSS-Protection: 1; mode=block

; mode=block verhindert, dass der Browser auf die Idee kommt, Sachen zu korrigieren und anschliessend korrigiert darzustellen. Falls ; mode=block nicht gesetzt ist, bietet der XSS-Filter damit perfiderweise eine neue Angriffsfläche. Jeglicher Header, welcher als Schutz per Meta-Tag definiert wird, wie z.B. der folgende Content-Security-Policy Header

<meta http-equiv="Content-Security-Policy" content="super-sichere-csp" />

kann ausgehebelt werden. Das liegt wieder mal an Internet Explorer und seinem Nachfolger Microsoft Edge. Im Gegensatz zu anderen Browsern wie Firefox und Chrome durchläuft Internet Explorer zuerst die komplette Seite, um nach Meta-Tags zu suchen. “Dank” seines XSS Filters, erkennt er, wenn als Parameter

?a=<meta http-equiv="

mitgeschickt wird, dieser auch im Body der Webseite vorkommt und wertet es deshalb als Angriff. Standardmässig ersetzt IE einfach eines der Zeichen und hebelt somit den Schutz aus.

Wenn ; mode=block fehlt, können damit allerdings nicht nur Schutzmechanismen umgangen werden. Es können sogar neue Schwachstellen eingeführt werden! Lesenswert dazu ist Security Researcher Masato Kinugawas Paper X-XSS-Nightmare.

X-Frame-Options

Der X-Frame-Options Header ist bekannt, weil er erstellt wurde um Click-Jacking Angriffe abzuwehren. Allerdings schützt der Header auch gegen eine Reihe von speziellen XSS, wie dem Docmode-Problem der Krücke des Internets, Microsoft Internet Explorer, Drag’n‘Drop XSS, Copy&Paste XSS, Invisible Site-Wide XSS, und sogar gegen Unterlaufen der Content-Security-Policy. Security Engineer Frederik Braun und Security Researcher Mario Heiderich haben ein sehr ausführliches und empfehlenswertes Paper geschrieben, welches diese und weitere Schwachstellen beschreibt, die durch den X-Frame-Options Header geschützt sind.

Das Docmode-Problem ist besonders und verdient seinen eigenen Absatz. Internet Explorer versucht auf Biegen und Brechen alte und kaputte Webseiten zu unterstützen. Manche dieser Webseite laufen allerdings nur in alten Versionen des Browsers. Um diese korrekt anzuzeigen kann Internet Explorer 11 dazu veranlasst werden sich zu verhalten als sei er Internet Explorer 8. Dies kann erreicht werden mit folgendem Header:

X-UA-Compatible: IE=8

Das führt allerdings auch dazu, dass der Browser wieder durch alle alte Schwachstellen verwundbar ist. Da der Docmode vom Parent-Frame vererbt wird, kann Internet Explorer dazu veranlasst werden, eine aktuelle Seite durch framen in einem alten Docmode anzuzeigen. Ein Beispiel einer geframten Seite mit altem, verwundbarem Docmode:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <head>
<html xmlns="http://www.w3.org/1999/xhtml">
    <title>Test Layout</title>
	<meta http-equiv="X-UA-Compatible" content="IE=8" />
    <style type="text/css">
      body, html
	    {
          margin: 0; padding: 0; height: 100%; overflow: hidden;
        }
		#content
        {
          position:absolute; left: 0; right: 0; bottom: 0; top: 0px;
        }
  </style>
  </head>
  <body>
    <div id="content">
      <iframe width="100%" height="100%" frameborder="0" src="http://domain-without-xfo-header.tld" />
    </div>
  </body>
</html>

Dadurch wird der X-Frame-Options zu einem der wichtigsten, momentan existierenden Security Header. Für diejenigen, die sich fragen, ob dieses Problem in Edge weiterhin besteht ist die Antwort eindeutig Jain. Auf der einen Seite unterstützt Edge alte Docmodes nicht mehr, was gut ist. Aber es wäre nicht Microsoft, wenn die Lösung nicht einen Haken hätte. Edge schlägt in dem Fall eines alten Docmode Headers dem Benutzer nämlich vor, die Seite in Internet Explorer zu öffnen.

Framing sollte verboten werden mittels

X-Frame-Options: DENY

oder maximal sich selbst erlauben durch folgenden Header:

X-Frame-Options: SAMEORIGIN

Dieser Header wird abgelöst durch die CSP Policy frame-ancestors. Bis dies allerdings tatsächlich geschehen ist, wird empfohlen beides zu setzen.

Content-Security-Policy

Etwas komplizierter, dafür umso mächtiger, ist der Content-Security-Policy (CSP) Header. In ihm lässt sich mittels Richtlinie definieren, welche Quellen verwendet werden dürfen. Das heisst, wenn man Skripte einbindet, nur vom eigenen Server oder auch von extern oder nur von spezifischen externen Hosts. Momentan wird an der Content Security Policy 2.0 W3C Candidate Recommendation gearbeitet.

Experimentelle Implementationen benutzten die Namen X-WebKit-CSP und X-Content-Security-Policy. Microsoft Internet Explorer hat den Sprung nicht geschafft und benutzt immer noch X-Content-Security-Policy, im Gegensatz zu allen anderen Browsern. Glücklicherweise hat Microsoft immerhin bei ihrem neuen Browser Edge eingesehen, dass Standards einen Sinn haben, und unterstützt dort den regulären CSP Header. Laut Can I use wird der CSP Header von knapp 80 Prozent aller Browser weltweit unterstützt.

Die möglichen Optionen sind:

Es gibt insbesondere zwei Optionen, denen man sich anfangs widmen sollte, nämlich default-src und report-uri. Grundsätzlich sollte default-src so restriktiv wie möglich konfiguriert sein.

Schlüsselwörter dazu sind

Es ist eigentlich selbsterklärend, dass unsafe-inline und unsafe-eval unsicher sind, und deshalb nicht verwendet werden sollten.

report-uri gibt an, wohin Verletzungen der Richtlinie geschickt werden, damit man evaluieren kann, wo sie bricht. Damit es während der Richtlinienerstellung und dem eventuellen Anpassen von unsicheren Webseitenelementen nicht zu einem Ausfall kommt, empfiehlt es sich mit Content-Security-Policy-Report-Only anzufangen.

Content-Security-Policy-Report-Only: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'none'

Falls man bei anfänglichen Experimenten noch nicht seine eigene report-uri zur Verfügung stellen möchte, so kann man dies auf der Seite REPORT URI.

Von hier aus kann dann die Richtlinie entweder notwendigerweise gelockert, oder die Webseite korrigiert werden. Twitter, als einer der frühen Umsetzer von CSP auf ihrer Webseite, hat einen Erfahrungsbericht online gestellt.

CSP Bypasses und Header Injections sind in den letzten sechs Jahren einiges rarer geworden, sodass sich der Aufwand der Konfiguration von CSP lohnt. Empfehlenswert ist ein Blick auf den Content Security Policy Quick Reference Guide. Hier finden sich weitere Informationen zum Header und dessen Konfiguration. Auch lesenswert ist das CSP Cheat Sheet von Security Consultant Scott Helme.

Aktueller Stand

Die Situation im Internet (Daten erhoben mit Shodan) sieht folgendermassen aus im Bezug auf Security Header:

Die Werte sind jeweils prozentuale Angaben auf den kompletten Verkehr der sich aus der Reihe ergibt. Die erste Datenzelle sagt also, dass 0.95% Weltweit aller Webseiten auf Port 443 den Strict-Transport-Security Header gesetzt haben.

Country and PortStrict-Transport-SecurityXFO DenyXFO SameoriginPublic-Key-PinningContent-TypeX-Xss-ProtectionX-Content-Type-OptionsContent-Security-Policy
80/tcp 0.17691.7509 25.15150.72830.40580.0233
443/tcp0.95220.44323.59700.010724.50870.67000.86950.1250
80/tcp 0.16541.1788 36.83490.51550.63620.1272
443/tcp2.69320.69245.93770.048335.29411.01181.51810.4765
80/tcp 0.11572.2089 32.30210.81620.50670.0553
443/tcp2.17141.20789.76150.014230.87041.00141.61200.2550

Es gibt insgesamt zwei Hauptaussagen die man daraus leicht ziehen kann.

  1. Kaum jemand scheint sich um Security Header zu kümmern und das obwohl einige davon wirklich leicht zu setzen sind. Die positive Ausnahme dazu bildet Content-Type mit Charset. Der wird auf über einem Viertel aller Seiten gesetzt.
  2. Die Schweiz als auch Deutschland stehen im weltweiten Vergleich gut da.

Home Sweet Home

Seine eigenen Header zu überprüfen ist noch einfacher als sie zu setzen. Eine Webseite, welche diese für einen überprüft ist zum Beispiel SecurityHeaders.io. Hierbei kann diese Seite als guter Indikator verwendet werden, bei der Content-Security-Policy gilt es allerdings darauf zu achten, dass die Seite keine vollständige Analyse des CSP Headers liefern kann. Was passieren kann, wenn man die CSP Konfiguration nicht richtig macht, beschreibt @fildedescriptor hier.

Es gibt noch weitere relevante Security Header. Dazu gibt es mehr im Artikel Big Brother oder: Wie ich lernte, Verschlüsselung zu lieben.

Über den Autor

Veit Hailperin

Veit Hailperin arbeitet seit 2010 im Bereich der Informationssicherheit. Seine Forschung konzentriert sich auf Network und Application Layer Security sowie auf den Schutz der Privatsphäre. Die Resultate präsentiert er an Konferenzen.

Links

Haben Sie Interesse an einem Penetration Test?

Unsere Spezialisten kontaktieren Sie gern!

×
Crypto-Malware

Crypto-Malware

Ahmet Hrnjadovic

TIBER-EU Framework

TIBER-EU Framework

Dominik Altermatt

Vertrauen und KI

Vertrauen und KI

Marisa Tschopp

Datenverschlüsselung in der Cloud

Datenverschlüsselung in der Cloud

Tomaso Vasella

Sie wollen mehr?

Weitere Artikel im Archiv

Sie brauchen Unterstützung bei einem solchen Projekt?

Unsere Spezialisten kontaktieren Sie gern!

Sie wollen mehr?

Weitere Artikel im Archiv