SSL im Browser weiter absichern – Ist SSL alleine nicht sicher genug?

SSL steht für „Secure Sockets Layer“ und ist eigentlich ein veralteter Begriff. Dennoch wird er weit häufiger verwendet und steht dadurch Synonym für seinen eigentlichen Nachfolger TLS („Transport Layer Security„). Ob eine Browserverbindung per TLS gesichert ist erkennt man leicht am entsprechenden Icon in der Browserleiste, oder am „s“ in „https://“. Leider blenden viele aktuelle Browser dieses Protokoll aus, so dass man sich nur noch auf die Icons verlassen kann. Im Screenshot sind 2 verschiedene Icons zu erkennen, da Facebook und die 1822direkt unterschiedliche Zertifikatstypen verwenden.
 

Zwei SSL-Zertifikate, wie man sie im Browser sieht

Zwei SSL-Zertifikate, wie man sie im Browser sieht


 
Facebook verwendet ein einfaches Zertifikat. Die Ausgabestelle bestätigt lediglich, dass das Zertifikat, mit dem Facebook seinen verschlüsselten Datenverkehr signiert, gültig ist. Ob es sich aber wirklich um Facebook handelt, ist bei diesem Zertifikat egal. Die 1822 hingegeben verwendet ein EV-Zertifikat („Extended Validation“). Hierbei bestätigt die Ausgabestelle nicht nur die Gültigkeit des Zertifikats, sondern auch dass der Inhaber tatsächlich die 1822 ist. Den dafür notwendigen Anruf, die Unterschriften und das Sichten von Kopien amtlicher Dokumente lassen sich die Ausgabestellen dabei fürstlich entlohnen.
 
Ohne ein solches Zertifikat wäre es ein leichtes sich als Angreifer zwischen dem Server und dem Browser zu setzen und den Datenverkehr abzuhören. bei einem solchen „Man in the middle„-Angriff täuscht der Angreifer nämlich einfach beiden Seiten vor, selbst der Client bzw. der Server zu sein. Somit kann er selbst kontrollieren, welche Schlüssel verwendet werden, und den Datenverkehr selbst entschlüsseln. Zertifikate, die über vertrauenswürdige Stellen ausgegeben werden, erschweren diesen Angriff. Zwar kann der Angreifer dem Server immer noch vorgaukeln, selbst der Client zu sein. Aber den Client kann er nicht mehr täuschen, da Verschlüsselung und Zertifikat nicht mehr passen. Der Browser zeigt eine Warnung an und es liegt am Anwender, diese ernst zu nehmen (oder zu ignorieren).
 
Das schönste SSL-Zertifikat allerdings hilft nichts, wenn der Server die Verschlüsselung nicht erzwingt. Und selbst wenn der Server so konfiguriert wurde, dass er Anfragen automatisch auf einen verschlüsselten Datenstrom umleitet, ist dies nicht sofort per Definition sicher. Denn der Nutzer tippt im Browser doch nur „upjers.com“ ein, ohne Protokoll. Der Browser erzeugt also eine Anfrage an „http://upjers.com“, ruft diese Seite unverschlüsselt auf und wird erst vom Server umgeleitet auf „https://upjers.com“. Während nun ein Angreifer, der zum Beispiel in einem offenen WLAN den Datenverkehr belauscht, durch die Umleitung keine Chance hat, die ins Login-Formular eingegebenen Nutzerdaten mitzulesen (Diese werden ja verschlüsselt übertragen), könnte er theoretisch bei diesem allerersten Aufruf von „http://upjers.com“ ein Session-Cookie abfangen, das unverschlüsselt übertragen wird. Mit diesem Cookie könnte er durchaus die Chance haben, sich als gültigen Nutzer auszugeben und dem eigentlichen Inhaber des Cookies Schaden zufügen (Session verfügen über weitere Maßnahmen, die Gültigkeit des Cookies festzustellen, zumindest sollten sie das).
 
Wie also verhindert man, dass ein Cookie unverschlüsselt übertragen wird? Das ist eigentlich ziemlich einfach, denn Cookies verfügen über ein Flag, das den Browser anweist, Cookies nur über verschlüsselte Verbindungen zu übertragen. Dieses Flag nennt sich „secure“-Flag.
 

Set-Cookie: PHPSESSID=46fd11bd3c93e387a10b7e78f56dfc50; path=/; domain=.upjers.com; secure; HttpOnly

 

Dieses kleine Wörtchen „secure“ sorgt dafür, dass der Browser das Cookie nur noch über verschlüsselte Datenströme überträgt (Natürlich macht das nur Sinn, wenn der Server ein solches Cookie ebenfalls nur über https setzt). „HttpOnly“ heißt hier übrigens, dass das Cookie nicht per JavaScript ausgelesen und geändert werden darf.

 

Es gibt noch eine weitere Möglichkeit, den Datenverkehr zwischen Client und Server etwas sicherer zu machen. Man kann verhindern, dass überhaupt noch Anfragen an http:// gestellt werden, nachdem der Nutzer das erste Mal die Seite besucht hat. Es könnten ja nach wie vor http://-Links zur Seite existieren, die wiederum unverschlüsselt angefragt werden und ggf. Daten über den Nutzer preisgeben, die wir nicht in fremde Hände geben wollen. Es müsste also eine Möglichkeit geben den Browser zu zwingen, Links selbstständig auf https:// umzuschreiben. Und natürlich gibt es diese Möglichkeit. Auch das ist ein simples Flag, das diesmal im http-Response-Header übertragen wird. Es nennt sich Strict-Transport-Security.  Der Header-Eintrag erwartet einen Parameter „max-age“, der in Sekunden angibt, wie lange der Browser ab sofort jeden http-Link direkt per https aufrufen soll. Somit können auch Links von Drittseiten und Suchmaschinen einem potentiellen Angreifer nicht mehr verraten, zu welchen Themen sich der Nutzer gerade auf unserer informiert. Und die Gefahr, Daten unverschlüsselt zu übertragen, ist dadurch ebenfalls gebannt. Und so sieht es aus:

 

Strict-Transport-Security: max-age=47336400

 

Diese einfache Zeile im Response-Header sorgt dafür, dass der Browser die nächsten 1.5 Jahre alle Aufrufe unserer Seite nur noch per https gestatten wird. So einfach kann es sein mit zwei kleinen Korrekturen die Sicherheit von SSL / TLS deutlich zu erhöhen und zufälliges Ausspähen z.B. im Café nahezu unmöglich zu machen. Und für die meisten „normalen“ Internetseiten lauert dort die größte Gefahr für den unbedarften Nutzer.

 

Hier noch ein vollständiger Header eines Aufrufs von https://upjers.com
HTTP/1.1 301 Moved Permanently
Date: Sun, 06 Apr 2014 11:32:36 GMT
Server: Apache/2.2.16 (Debian)
Strict-Transport-Security: max-age=47336400
P3P: CP=“invalid“
Set-Cookie: PHPSESSID=46fd11bd3c93e387a10b7e78f56dfc50; path=/; domain=.upjers.com; secure; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
location: https://de.upjers.com/
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html