7 Kommentare

Sichere SSL-Cookies in PHP

In einem heute auf Heise.de veröffentlichten Bericht wurde noch einmal auf ein seit längerem bekanntes Sicherheitsproblem mit SSL-verschlüsselten Websites und Cookies hingewiesen.

Das Szenario

Das Szenario für das Sicherheitsproblem ist das folgende:

Ein User verbindet sich mit einer durch SSL geschützten Website wie google-mail.

Er gibt über die sichere, da verschlüsselte Verbindung seine persönlichen Zugangsdaten ein.

Seinem Browser wird daraufhin eine eindeutige Session-Id mittels Cookie zugewiesen, so dass der Benutzer identifiziert bleibt.

Der Benutzer braucht nun seine Zugangsdaten für die Lebensdauer des Cookies nicht noch einmal eingeben, da er ja über das Cookie eindeutig identifiziert ist.

Würde ein Hacker die zugewiesene geheime Session-Id, bzw. Cookie-Id abfangen oder mitlesen können, so könnte dieser aber nun auch auf die persönlichen Daten des Benutzers zugreifen.

Solche Mithörattacken werden normalerweise durch die Verschlüsselung der Verbindung mittels SSL verhindert.

Das Problem ist nun aber, dass der Browser die Cookie-Id im Normalfall auch an nicht verschlüsselte Webseiten der gleichen Domain schickt um sich zu authentifizieren. Da Websites wie google-mail allerdings normalerweise alle Seiten verschlüsselt versenden, sollte dieser Fall nicht eintreten.

Der Trick besteht nun aber genau darin, dem Benutzer einen Link anzudrehen, der auf die nicht mit SSL geschützte Website des Betreibers verweist. Dies kann zum Beispiel einfach nur ein eingebettetes Bild in einem Webdokument sein. Öffnet der User dieses Webdokument, so versucht sein Browser automatisch eine nicht verschlüsselte Verbindung aufzubauen, um die Bilddatei anzuzeigen. Dabei sendet er eben die geheime Session-Id in Form des Cookies über diese unervschlüsselte Verbindung.

Um solche Tricks zu verhindern, gibt es die Möglichkeit, für ein Cookie das sogenannte Secure-Flag zu setzen. Damit wird dem Browser mitgeteilt, dass das Cookie nur über verschlüsselte Verbindungen zu benutzen ist. Somit würde der Browser das Cookie also im oben genannten Beispiel eben nicht mehr über die unverschlüsselte Verbindung mitsenden.

Das Secure-Flag muss aber von der Website gesetzt werden, die das Cookie zuweist. Da dies bei vielen Webdiensten nicht erfolgt, gibt es sehr viele verwundbare Systeme, die zwar mit SSL-Verschlüsselung arbeiten, aber ein Mithören allenfalls erschweren, anstatt es tatsächlich zu verhindern.

Secure-Flag für ein Session-Cookie in PHP setzen

In PHP gibt es nun folgende Ansatzpunkte, um die oben beschriebene Lücke zu schließen:

Benutzt man den Befehl session_start(), um die automatische Session-Verwaltung von PHP zu nutzen, so muss vorher immer session_set_cookie_params() mit entsprechenden Parametern aufgerufen werden.

Die Syntax für session_set_cookie_params() lautet dabei wie folgt (Quelle: PHP.net):

void session_set_cookie_params (
  int lifetime
  [, string path
  [, string domain
  [, bool secure
  [, bool httponly]]]]
)

lifetime spezifiziert die Cookie-Lebensdauer, die an den Browser geschickt wird, in Sekunden. Der Wert 0 bedeutet “bis der Browser geschlossen wird.” Grundeinstellung 0.

path spezifiziert den Pfad, in dem das Session-Cookie gesetzt wird. Grundeinstellung /.

domain spezifiziert die Domain, unter der das Session-Cookie gesetzt wird. In der Grundeinstellung überhaupt keine, was bedeutet, dass entsprechend der Spezifikation für Cookies der Hostname des Servers verwendet wird, der das Cookie erzeugt hat.

secure spezifiziert, ob Cookies nur über sichere Verbindungen geschickt werden sollen. Grundeinstellung off. Diese Einstellung wurde in PHP 4.0.4 hinzugefügt

httponly markiert das Cookie als nur über das HTTP-Protokoll zugänglich. Das bedeutet, dass für Skriptsprachen wie z.B. JavaScript nicht zugänglich ist. Diese Einstellung kann helfen, Identitätsdiebstahl durch XSS-Angriffe zu reduzieren (obwohl es nicht von allen Browsern unterstützt wird).

Entscheidend ist hier der secure-Parameter. Wird dieser auf TRUE gesetzt, so wird das vergebene Cookie so behandelt, dass es fortan nur noch über SSL-verschlüsselte Verbindungen genutzt wird.

Vergibt man seine eigenen Session-Cookies mittels setcookie(), so ist auch hier zu beachten, dass der secure-Parameter auf jeden Fall auf TRUE zu setzen ist. Nur so ist sichergestellt, dass das Cookie nur über SSL-verschlüsselte Verbindungen genutzt werden wird.

Abschließende Bemerkungen

Wie bereits gesagt, das Ganze macht nur Sinn, wenn man über eine SSL-verschlüsselte Verbindung auf die Website zugreift. Bietet man auch unverschlüsselten Zugriff auf das System, so sollte man vor dem Aufruf von session_set_cookie_params() noch überprüfen, ob auch wirklich eine HTTPS-Verbindung vorliegt. Die Überprüfung auf eine HTTPS-Verbindung könnte zum Beispiel folgendermaßen aussehen:

if (isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) { ... }

Stand: 14.08.2008, 12:16 Uhr

7 Kommentare

  1. Hallo,
    vielen Dank für diesen sinnvollen Beitrag. Genau, wonach ich nach dieser meldung gesucht hatte.
    Ich werde deine Tipps gleich mal beherzigen.
    Jürgen

  2. Toller Artikel! Danke

  3. Danke, das war einfach und ausführlich erklärt!

  4. Hallo,

    Schade, dass Du keine Artikel mehr schreibst. Nach dem letzten Beitrag habe ich mir noch Mehr solcher Qualität erhofft.

    Andi

  5. Tut mir leid, aber im Moment fehlt mir ein wenig die Zeit. Kommt aber bestimmt mehr ;)

  6. Hi, Vielen ank für diesen Post. Ich würde mich auch freuen wenn du wieder neue Artikel einstellst.

    Dankeschön.

  7. Danke für den Artikel, muss ich mich wohl auch mal mit befassen.

Kommentieren