Zum Inhalt springen

Session Fixation

CWE-384OWASP A07:2021Aktualisiert 31. August 20266 Min. Lesezeit

Session Fixation ist eine Schwachstelle, bei der ein Angreifer dem Opfer im Voraus eine Session ID unterschiebt, die beim Login nicht erneuert wird. Seine eigene Kopie dieser ID gehört danach zu einer authentifizierten Sitzung, sodass er im Konto mitfährt. Die strukturelle Lösung ist, die Session ID bei jeder Rechteänderung neu zu erzeugen und die alte Sitzung sofort zu verwerfen.

Beim Login ändert sich in vielen Anwendungen genau eine Sache: der Inhalt der Sitzung. Die lange Zeichenfolge im Cookie bleibt exakt dieselbe, während ihre Bedeutung von “anonymer Besucher” zu “angemeldeter Benutzer” wechselt. Wer diese Zeichenfolge schon kannte, bevor Sie sich angemeldet haben, verfügt danach über Ihr Konto. Das ist Session Fixation, und die Abhilfe kostet meist eine einzige Zeile Code.

Was ist Session Fixation?

Session Fixation ist eine Schwachstelle, bei der ein Angreifer im Voraus festlegt, welche Sitzungskennung ein Opfer verwendet, und die Anwendung diese Kennung beim Login nicht ersetzt. Die Session ID, ausgeschrieben Session Identifier, ist das Einzige, was der Server noch benötigt, um zu wissen, wer Sie sind. Wird sie nicht ausgetauscht, sobald die Sitzung an Wert gewinnt, wandert der Angreifer mit: Seine Kopie der ID gehört plötzlich zu einem angemeldeten Konto.

Ein Vergleich aus dem Alltag: die Garderobe eines Theaters. Normalerweise erhalten Sie eine frische Marke, wenn Sie Ihren Mantel abgeben. Nun drückt Ihnen jemand am Eingang seine eigene Marke in die Hand, von der er ein zweites Exemplar besitzt, und die Garderobe übernimmt diese Nummer einfach, statt eine neue auszugeben. Ihr Mantel hängt dann an einem Haken, dessen Nummer zwei Personen kennen, und wer zuerst erscheint, nimmt ihn mit.

Der Unterschied zum Session Hijacking liegt in der Reihenfolge. Beim Hijacking übernimmt der Angreifer eine Sitzung, die bereits authentifiziert ist, etwa durch ein gestohlenes Cookie. Bei der Fixation kennt er die ID, bevor sich jemand anmeldet, und überlässt dem Opfer die Authentifizierung. Danach muss er nichts mehr abfangen, was den Angriff leise macht und in Protokollen kaum auffällt.

Eine solche ID lässt sich auf mehreren Wegen platzieren. Eine Anwendung, die eine Sitzungskennung aus der URL annimmt, übernimmt jeden Wert, den ein Angreifer in einen Link schreibt. Ein Cookie kann außerdem von einer Subdomain aus gesetzt werden, die der Angreifer kontrolliert, denn Cookies sind nicht je Subdomain getrennt, wie es die Origin ist. Und jedes Cross-Site Scripting irgendwo auf der Domain genügt, um das Cookie direkt zu schreiben.

Wie funktioniert ein Session-Fixation-Angriff?

Nehmen wir eine Anmeldemaske, die die Sitzung startet, das Passwort prüft und den Benutzer anschließend in der Sitzung ablegt. Der Entwickler hält die Arbeit damit für erledigt, ersetzt die Kennung selbst jedoch nie.

Verwundbar:

<?php
session_start();

$user = find_user($_POST['email']);

if ($user && password_verify($_POST['password'], $user['hash'])) {
    // Die Session ID bleibt unverändert, nur der Inhalt wechselt
    $_SESSION['user_id']  = $user['id'];
    $_SESSION['is_admin'] = $user['is_admin'];

    header('Location: /account');
    exit;
}

Der Angreifer wählt zunächst einen Wert und sorgt dafür, dass der Browser des Opfers ihn mitsendet. Die Anfrage, mit der das Opfer auf der Anmeldemaske landet, sieht dann so aus:

GET /login HTTP/1.1
Host: app.example.com
Cookie: PHPSESSID=b7f1c0a94e2d4c8f9a1e6b3d0c5f8a27

Ohne strenge Prüfung legt der Server eine neue Sitzung unter dem gelieferten Namen an, statt eine eigene Kennung auszugeben. Das Opfer gibt sein Passwort ein, die Prüfung gelingt, und $_SESSION['user_id'] wird gefüllt. Die ID im Cookie lautet allerdings weiterhin b7f1c0a94e2d4c8f9a1e6b3d0c5f8a27, und die kannte der Angreifer von Anfang an. Er setzt dasselbe Cookie in seinem eigenen Browser, ruft /account auf und ist drin, ohne je ein Passwort gesehen zu haben.

Die Lösung besteht darin, die Kennung genau dann zu ersetzen, wenn die Sitzung ihre Bedeutung ändert. In PHP leistet das session_regenerate_id(true): Es wird eine neue ID vergeben und die alte Sitzung gelöscht. Zusätzlich weist die Einstellung session.use_strict_mode jede ID zurück, die der Server nicht selbst ausgegeben hat, sodass das Platzieren eines Wertes schon an der ersten Anfrage scheitert.

Sicher:

<?php
// php.ini: session.use_strict_mode = 1 und session.use_only_cookies = 1
session_start();

$user = find_user($_POST['email']);

if ($user && password_verify($_POST['password'], $user['hash'])) {
    // Neue ID, alte Sitzung sofort gelöscht
    session_regenerate_id(true);

    $_SESSION['user_id']  = $user['id'];
    $_SESSION['is_admin'] = $user['is_admin'];

    header('Location: /account');
    exit;
}

Dem Angreifer bleibt jetzt eine ID, die nach der Anmeldung des Opfers ins Leere zeigt. Seine Vorbereitung taugt zudem für keinen zweiten Versuch, weil der Server im strengen Modus jeden erfundenen Wert sofort verwirft.

Rufen Sie session_regenerate_id immer mit true auf. Ohne dieses Argument erhält der Benutzer zwar eine neue ID, die alte Sitzung besteht serverseitig aber weiter, samt der gerade eingetragenen Benutzerdaten. Der Angreifer arbeitet dann schlicht mit der ID weiter, die er platziert hatte, und die Schwachstelle ist lediglich besser versteckt.

Welche Auswirkungen hat Session Fixation?

Eine gelungene Session Fixation bedeutet die vollständige Übernahme des Kontos, mit genau den Rechten des Opfers. Bei einem gewöhnlichen Benutzer heißt das Einsicht in personenbezogene Daten, Bestellungen oder Vorgänge sowie die Möglichkeit, in dessen Namen zu handeln. Trifft es ein Administratorkonto, reicht der Schaden bis zur Verwaltung anderer Benutzer und zur Konfiguration der Anwendung selbst.

Der Schweregrad reicht von mittel bis hoch, und diese Spanne ist begründet. Der Angreifer braucht zweierlei: einen Weg, die ID in den Browser des Opfers zu bekommen, und ein Opfer, das sich danach tatsächlich anmeldet. Fällt die erste Bedingung weg, weil Sie keine Subdomains teilen, keine Sitzungskennungen aus URLs annehmen und kein Cross-Site Scripting haben, bleibt das Risiko begrenzt. Läuft die Anwendung dagegen auf einer geteilten Domain mit vielen Subdomains, oder handelt es sich um ein Portal, in dem sich Administratoren täglich anmelden, wiegt derselbe Fehler deutlich schwerer.

Geschäftlich übersetzt sich das in unberechtigte Transaktionen, Zugriff auf personenbezogene Daten mit Meldepflicht gegenüber der Aufsichtsbehörde und Betrug, der auf den Namen eines echten Benutzers läuft. Der letzte Punkt wiegt in einer Auseinandersetzung schwer: Die Protokolle zeigen eine normale Anmeldung und danach normales Verhalten, denn technisch ist nichts Ungewöhnliches passiert.

Wie erkennen Sie Session Fixation?

Der Test ist kurz und benötigt kein besonderes Werkzeug. Notieren Sie den Wert des Sitzungscookies vor der Anmeldung, melden Sie sich an und vergleichen Sie den Wert danach. Bleibt er gleich, erneuert die Anwendung die Kennung nicht und die Schwachstelle liegt vor. Wiederholen Sie den Vergleich rund um einen zweiten Faktor, einen Rollenwechsel und eine Passwortänderung, denn viele Anwendungen erneuern die ID nur beim ersten Anmeldeschritt.

Prüfen Sie außerdem, ob der Server einen selbst erfundenen Wert annimmt: Setzen Sie ein Cookie mit einer nie vergebenen ID, rufen Sie eine Seite auf und beobachten Sie, ob Sie eine gültige Sitzung erhalten. Achten Sie darauf, ob die Session ID irgendwo in einer URL auftaucht, in Weiterleitungen, in Referer-Headern oder in teilbaren Links, und ob das Cookie auf den Host beschränkt ist, zu dem es gehört.

Automatisierte Scanner melden bestenfalls, dass sich das Cookie nicht ändert, und übersehen die Fälle hinter einem zweiten Faktor oder in einer Impersonation-Funktion, weil sie diesen Ablauf nie durchlaufen. Manuelles Testen mit zwei getrennten Browsersitzungen zeigt das Verhalten dagegen zuverlässig. AssistSec prüft die Sitzungsverwaltung im Rahmen eines Penetrationstests standardmäßig mit und weist je Befund nach, mit welcher ID eine Sitzung nach der Anmeldung noch nutzbar war.

Wie verhindern Sie Session Fixation?

  • Erneuern Sie die Session ID bei jeder Rechteänderung. Bei der Anmeldung, nach einem erfolgreichen zweiten Faktor, beim Wechsel von Rolle oder Mandant, bei der Impersonation durch einen Administrator und bei einer Passwortänderung.
  • Löschen Sie die alte Sitzung serverseitig. Eine neue ID auszugeben, während die vorherige Sitzung weiterlebt, verschiebt das Problem nur an eine unauffälligere Stelle.
  • Akzeptieren Sie nur Kennungen, die Sie selbst vergeben haben. Schalten Sie den strengen Modus Ihrer Sitzungsbibliothek ein, damit ein unbekannter Wert zurückgewiesen statt übernommen wird.
  • Halten Sie die Session ID aus der URL heraus. Ausschließlich Cookies, niemals Sitzungskennungen in Query-Strings oder Pfaden; diese lecken über Protokolle, Browserverlauf und geteilte Links.
  • Setzen Sie die Cookie-Attribute streng. HttpOnly, Secure, ein passender SameSite-Wert und nach Möglichkeit das Präfix __Host-, damit das Cookie an genau einen Host gebunden bleibt.
  • Behalten Sie Ihre Subdomains im Griff. Jede Subdomain kann Cookies für die übergeordnete Domain setzen; eine vergessene oder übernommene Subdomain wird damit zum Ausgangspunkt für diesen Angriff.
  • Begrenzen Sie die Lebensdauer und machen Sie das Abmelden wirksam. Eine Leerlaufzeit, eine absolute Höchstdauer und das serverseitige Ungültigmachen beim Logout verkleinern das Fenster, in dem eine platzierte ID noch etwas wert ist.

Quellen

Häufige Fragen

Was ist der Unterschied zwischen Session Fixation und Session Hijacking?

Beim Session Hijacking gelangt ein Angreifer an eine bereits authentifizierte Sitzung, etwa indem er ein Cookie über Cross-Site Scripting oder unverschlüsselten Verkehr stiehlt. Bei Session Fixation ist die Reihenfolge umgekehrt: Der Angreifer kennt die ID, bevor sich überhaupt jemand anmeldet, und lässt das Opfer die Authentifizierung für ihn erledigen. Das Ergebnis ist dasselbe, doch er muss im Nachhinein nichts mehr abfangen.

Sind moderne Frameworks standardmäßig gegen Session Fixation geschützt?

Weitgehend ja. Laravel, Django, Rails, ASP.NET Core und Spring Security erneuern die Session ID beim Login, sofern Sie deren eigenen Authentifizierungsmechanismus verwenden. Probleme entstehen vor allem bei selbst gebauten Anmeldemasken, bei einem zweiten Login-Pfad neben dem regulären und rund um Step-up-Authentifizierung oder Impersonation, wo sich die Rechte ändern, ohne dass formal eine neue Anmeldung stattfindet.

Helfen HttpOnly- und Secure-Cookies gegen Session Fixation?

Sie helfen, lösen das Problem aber nicht. HttpOnly hält JavaScript vom Cookie fern, Secure verhindert den Versand über einfaches HTTP, womit zwei Wege zum Setzen oder Abfangen einer ID wegfallen. Ein Angreifer, der das Cookie von einer Subdomain aus setzt oder eine ID über einen URL-Parameter einschleust, kommt weiterhin durch. Erst das Erneuern der ID beim Login beseitigt die Ursache.

Wann muss ich die Session ID erneuern?

Bei jeder Änderung der Berechtigungsstufe. Das betrifft in jedem Fall die Anmeldung, ebenso den Abschluss eines zweiten Faktors, den Wechsel von Rolle oder Mandant, die Übernahme eines Kontos durch einen Administrator und eine Passwortänderung. Erneuern Sie die ID auch beim Abmelden und löschen Sie die Sitzung dabei serverseitig, statt nur das Cookie zu entfernen.

Verwandte Artikel

Zum Suchen / drücken · Esc